commit de4d06c64b47df77b232e0e5a5054b18e5c8ec33
parent 994b3549a765edae6c6e7b49270085528d5b9a77
Author: rwa <apollo@rw-net.de>
Date: Sat, 27 Oct 2018 21:15:14 +0200
implements #14
add posibility to register to tool for Windows Explorer folder context menu
Diffstat:
5 files changed, 234 insertions(+), 13 deletions(-)
diff --git a/JpegDivider/JpegDivider.csproj b/JpegDivider/JpegDivider.csproj
@@ -44,6 +44,7 @@
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="UacHelper.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
diff --git a/JpegDivider/JpegDivider.csproj.user b/JpegDivider/JpegDivider.csproj.user
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
- <StartArguments>/%3f</StartArguments>
+ <StartArguments>register</StartArguments>
<StartWorkingDirectory>C:\Users\winuser\Pictures</StartWorkingDirectory>
</PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+ <StartArguments>register</StartArguments>
+ </PropertyGroup>
</Project>
\ No newline at end of file
diff --git a/JpegDivider/Program.cs b/JpegDivider/Program.cs
@@ -1,4 +1,5 @@
-using System;
+using Microsoft.Win32;
+using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@@ -15,10 +16,19 @@ namespace JpegDivider
Console.WriteLine("Leave args blank or give exactly one dir!");
}
- if (args[0].Equals("help") || args[0].Equals("/h") || args[0].Equals("/?"))
+ switch (args[0].ToLower())
{
- showHelp();
- return;
+ case "help":
+ ShowHelp();
+ return;
+ case "register":
+ RegisterShellExt();
+ return;
+ case "deregister":
+ DeregisterShellExt();
+ return;
+ default:
+ break;
}
string dir;
@@ -31,8 +41,14 @@ namespace JpegDivider
dir = Directory.GetCurrentDirectory();
}
- Console.WriteLine($"working dir: {dir}");
+ Divide(dir);
+ Console.ReadKey();
+ }
+
+ private static void Divide(string dir)
+ {
+ Console.WriteLine($"working directory: {dir}");
// create
string sepDir = Path.Combine(dir, "JPEG");
if (!Directory.Exists(sepDir))
@@ -60,11 +76,76 @@ namespace JpegDivider
}
Console.WriteLine("Finished.");
+ }
- Console.ReadKey();
+ private static void DeregisterShellExt()
+ {
+ if (!UacCheck) { return; }
+
+ string MenuName = "Folder\\shell\\JpegDivider";
+ string Command = "Folder\\shell\\JpegDivider\\command";
+
+ try
+ {
+ RegistryKey reg = Registry.ClassesRoot.OpenSubKey(Command);
+ if (reg != null)
+ {
+ reg.Close();
+ Registry.ClassesRoot.DeleteSubKey(Command);
+ }
+ reg = Registry.ClassesRoot.OpenSubKey(MenuName);
+ if (reg != null)
+ {
+ reg.Close();
+ Registry.ClassesRoot.DeleteSubKey(MenuName);
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Failed to remove application from Windows Explorer context menu:{Environment.NewLine}{ex.Message}");
+ }
}
- private static void showHelp()
+ private static void RegisterShellExt()
+ {
+ if (!UacCheck) { return; }
+
+ string MenuName = "Folder\\shell\\JpegDivider";
+ string Command = "Folder\\shell\\JpegDivider\\command";
+
+ RegistryKey regmenu = null;
+ RegistryKey regcmd = null;
+ try
+ {
+ regmenu = Registry.ClassesRoot.CreateSubKey(MenuName);
+ if (regmenu != null)
+ {
+ regmenu.SetValue("", "JpegDivider");
+ }
+ regcmd = Registry.ClassesRoot.CreateSubKey(Command);
+ if (regcmd != null)
+ {
+ regcmd.SetValue("", $"\"{Assembly.GetEntryAssembly().Location}\" \"%L\"");
+ }
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Failed to register application to Windows Explorer context menu:{Environment.NewLine}{ex.Message}");
+ }
+ finally
+ {
+ if (regmenu != null)
+ {
+ regmenu.Close();
+ }
+ if (regcmd != null)
+ {
+ regcmd.Close();
+ }
+ }
+ }
+
+ private static void ShowHelp()
{
Console.WriteLine($"{Assembly.GetExecutingAssembly().GetName().Name} - Version {Assembly.GetExecutingAssembly().GetName().Version}");
Console.WriteLine("published under BSD 3 - Clause License");
@@ -72,11 +153,30 @@ namespace JpegDivider
Console.WriteLine("https://gitlab.com/guzzisti1/rawfilewizard");
Console.WriteLine("");
Console.WriteLine("divide jpegs from raw files by moving them to subfolder JPEG");
+ Console.WriteLine("the subfolder is created if not existing");
Console.WriteLine("");
- Console.WriteLine("Commandline:");
+ Console.WriteLine("commandline:");
Console.WriteLine("jpegdivider.exe - move jpegs from current working dir to subfolder");
Console.WriteLine("jpgedivider.exe <path_to_folder> - move jpegs from specified folder to subfolder");
- Console.WriteLine("jpgedivider.exe /h|/?|help - show this help");
+ Console.WriteLine("jpegdivider.exe register - register the program to folder context menu, run JpegDivider on a selected folder from Windows Explorer");
+ Console.WriteLine("jpegdivider.exe deregister - remove the programm from folder context menu");
+ Console.WriteLine("jpgedivider.exe help - show this help");
+ }
+
+ private static bool UacCheck
+ {
+ get
+ {
+ if (UacHelper.IsProcessElevated)
+ {
+ return true;
+ }
+ else
+ {
+ Console.WriteLine("Need to run as administrator / with elevated UAC rights!");
+ return false;
+ }
+ }
}
}
-}
+}
+\ No newline at end of file
diff --git a/JpegDivider/Properties/AssemblyInfo.cs b/JpegDivider/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: AssemblyVersion("1.1.0.0")]
+[assembly: AssemblyFileVersion("1.1.0.0")]
diff --git a/JpegDivider/UacHelper.cs b/JpegDivider/UacHelper.cs
@@ -0,0 +1,115 @@
+using Microsoft.Win32;
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using System.Security.Principal;
+
+namespace JpegDivider
+{
+ public static class UacHelper
+ {
+ private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
+ private const string uacRegistryValue = "EnableLUA";
+
+ private static uint STANDARD_RIGHTS_READ = 0x00020000;
+ private static uint TOKEN_QUERY = 0x0008;
+ private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
+
+ [DllImport("advapi32.dll", SetLastError = true)]
+ public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);
+
+ public enum TOKEN_INFORMATION_CLASS
+ {
+ TokenUser = 1,
+ TokenGroups,
+ TokenPrivileges,
+ TokenOwner,
+ TokenPrimaryGroup,
+ TokenDefaultDacl,
+ TokenSource,
+ TokenType,
+ TokenImpersonationLevel,
+ TokenStatistics,
+ TokenRestrictedSids,
+ TokenSessionId,
+ TokenGroupsAndPrivileges,
+ TokenSessionReference,
+ TokenSandBoxInert,
+ TokenAuditPolicy,
+ TokenOrigin,
+ TokenElevationType,
+ TokenLinkedToken,
+ TokenElevation,
+ TokenHasRestrictions,
+ TokenAccessInformation,
+ TokenVirtualizationAllowed,
+ TokenVirtualizationEnabled,
+ TokenIntegrityLevel,
+ TokenUIAccess,
+ TokenMandatoryPolicy,
+ TokenLogonSid,
+ MaxTokenInfoClass
+ }
+
+ public enum TOKEN_ELEVATION_TYPE
+ {
+ TokenElevationTypeDefault = 1,
+ TokenElevationTypeFull,
+ TokenElevationTypeLimited
+ }
+
+ public static bool IsUacEnabled
+ {
+ get
+ {
+ RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false);
+ bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
+ return result;
+ }
+ }
+
+ public static bool IsProcessElevated
+ {
+ get
+ {
+ if (IsUacEnabled)
+ {
+ IntPtr tokenHandle;
+ if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
+ {
+ throw new ApplicationException("Could not get process token. Win32 Error Code: " + Marshal.GetLastWin32Error());
+ }
+
+ TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;
+
+ int elevationResultSize = Marshal.SizeOf((int)elevationResult);
+ uint returnedSize = 0;
+ IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);
+
+ bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize);
+ if (success)
+ {
+ elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr);
+ bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
+ return isProcessAdmin;
+ }
+ else
+ {
+ throw new ApplicationException("Unable to determine the current elevation.");
+ }
+ }
+ else
+ {
+ WindowsIdentity identity = WindowsIdentity.GetCurrent();
+ WindowsPrincipal principal = new WindowsPrincipal(identity);
+ bool result = principal.IsInRole(WindowsBuiltInRole.Administrator);
+ return result;
+ }
+ }
+ }
+ }
+}
+\ No newline at end of file