Browse code

implements #14

add posibility to register to tool for Windows Explorer folder context menu

rwa authored on 27.10.2018 21:15:14
Showing 5 changed files

... ...
@@ -44,6 +44,7 @@
44 44
   <ItemGroup>
45 45
     <Compile Include="Program.cs" />
46 46
     <Compile Include="Properties\AssemblyInfo.cs" />
47
+    <Compile Include="UacHelper.cs" />
47 48
   </ItemGroup>
48 49
   <ItemGroup>
49 50
     <None Include="App.config" />
... ...
@@ -1,7 +1,10 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 3
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
4
-    <StartArguments>/%3f</StartArguments>
4
+    <StartArguments>register</StartArguments>
5 5
     <StartWorkingDirectory>C:\Users\winuser\Pictures</StartWorkingDirectory>
6 6
   </PropertyGroup>
7
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
8
+    <StartArguments>register</StartArguments>
9
+  </PropertyGroup>
7 10
 </Project>
8 11
\ No newline at end of file
... ...
@@ -1,4 +1,5 @@
1
-using System;
1
+using Microsoft.Win32;
2
+using System;
2 3
 using System.Collections.Generic;
3 4
 using System.IO;
4 5
 using System.Linq;
... ...
@@ -15,10 +16,19 @@ namespace JpegDivider
15 16
                 Console.WriteLine("Leave args blank or give exactly one dir!");
16 17
             }
17 18
 
18
-            if (args[0].Equals("help") || args[0].Equals("/h") || args[0].Equals("/?"))
19
+            switch (args[0].ToLower())
19 20
             {
20
-                showHelp();
21
-                return;
21
+                case "help":
22
+                    ShowHelp();
23
+                    return;
24
+                case "register":
25
+                    RegisterShellExt();
26
+                    return;
27
+                case "deregister":
28
+                    DeregisterShellExt();
29
+                    return;
30
+                default:
31
+                    break;
22 32
             }
23 33
 
24 34
             string dir;
... ...
@@ -31,8 +41,14 @@ namespace JpegDivider
31 41
                 dir = Directory.GetCurrentDirectory();
32 42
             }
33 43
 
34
-            Console.WriteLine($"working dir: {dir}");
44
+            Divide(dir);
35 45
 
46
+            Console.ReadKey();
47
+        }
48
+
49
+        private static void Divide(string dir)
50
+        {
51
+            Console.WriteLine($"working directory: {dir}");
36 52
             // create 
37 53
             string sepDir = Path.Combine(dir, "JPEG");
38 54
             if (!Directory.Exists(sepDir))
... ...
@@ -60,11 +76,76 @@ namespace JpegDivider
60 76
             }
61 77
 
62 78
             Console.WriteLine("Finished.");
79
+        }
63 80
 
64
-            Console.ReadKey();
81
+        private static void DeregisterShellExt()
82
+        {
83
+            if (!UacCheck) { return; }
84
+
85
+            string MenuName = "Folder\\shell\\JpegDivider";
86
+            string Command = "Folder\\shell\\JpegDivider\\command";
87
+
88
+            try
89
+            {
90
+                RegistryKey reg = Registry.ClassesRoot.OpenSubKey(Command);
91
+                if (reg != null)
92
+                {
93
+                    reg.Close();
94
+                    Registry.ClassesRoot.DeleteSubKey(Command);
95
+                }
96
+                reg = Registry.ClassesRoot.OpenSubKey(MenuName);
97
+                if (reg != null)
98
+                {
99
+                    reg.Close();
100
+                    Registry.ClassesRoot.DeleteSubKey(MenuName);
101
+                }
102
+            }
103
+            catch (Exception ex)
104
+            {
105
+                Console.WriteLine($"Failed to remove application from Windows Explorer context menu:{Environment.NewLine}{ex.Message}");
106
+            }
65 107
         }
66 108
 
67
-        private static void showHelp()
109
+        private static void RegisterShellExt()
110
+        {
111
+            if (!UacCheck) { return; }
112
+
113
+            string MenuName = "Folder\\shell\\JpegDivider";
114
+            string Command = "Folder\\shell\\JpegDivider\\command";
115
+
116
+            RegistryKey regmenu = null;
117
+            RegistryKey regcmd = null;
118
+            try
119
+            {
120
+                regmenu = Registry.ClassesRoot.CreateSubKey(MenuName);
121
+                if (regmenu != null)
122
+                {
123
+                    regmenu.SetValue("", "JpegDivider");
124
+                }
125
+                regcmd = Registry.ClassesRoot.CreateSubKey(Command);
126
+                if (regcmd != null)
127
+                {
128
+                    regcmd.SetValue("", $"\"{Assembly.GetEntryAssembly().Location}\" \"%L\"");
129
+                }
130
+            }
131
+            catch (Exception ex)
132
+            {
133
+                Console.WriteLine($"Failed to register application to Windows Explorer context menu:{Environment.NewLine}{ex.Message}");
134
+            }
135
+            finally
136
+            {
137
+                if (regmenu != null)
138
+                {
139
+                    regmenu.Close();
140
+                }
141
+                if (regcmd != null)
142
+                {
143
+                    regcmd.Close();
144
+                }
145
+            }
146
+        }
147
+
148
+        private static void ShowHelp()
68 149
         {
69 150
             Console.WriteLine($"{Assembly.GetExecutingAssembly().GetName().Name} - Version {Assembly.GetExecutingAssembly().GetName().Version}");
70 151
             Console.WriteLine("published under BSD 3 - Clause License");
... ...
@@ -72,11 +153,30 @@ namespace JpegDivider
72 153
             Console.WriteLine("https://gitlab.com/guzzisti1/rawfilewizard");
73 154
             Console.WriteLine("");
74 155
             Console.WriteLine("divide jpegs from raw files by moving them to subfolder JPEG");
156
+            Console.WriteLine("the subfolder is created if not existing");
75 157
             Console.WriteLine("");
76
-            Console.WriteLine("Commandline:");
158
+            Console.WriteLine("commandline:");
77 159
             Console.WriteLine("jpegdivider.exe - move jpegs from current working dir to subfolder");
78 160
             Console.WriteLine("jpgedivider.exe <path_to_folder> - move jpegs from specified folder to subfolder");
79
-            Console.WriteLine("jpgedivider.exe /h|/?|help - show this help");
161
+            Console.WriteLine("jpegdivider.exe register - register the program to folder context menu, run JpegDivider on a selected folder from Windows Explorer");
162
+            Console.WriteLine("jpegdivider.exe deregister - remove the programm from folder context menu");
163
+            Console.WriteLine("jpgedivider.exe help - show this help");
164
+        }
165
+
166
+        private static bool UacCheck
167
+        {
168
+            get
169
+            {
170
+                if (UacHelper.IsProcessElevated)
171
+                {
172
+                    return true;
173
+                }
174
+                else
175
+                {
176
+                    Console.WriteLine("Need to run as administrator / with elevated UAC rights!");
177
+                    return false;
178
+                }
179
+            }
80 180
         }
81 181
     }
82
-}
182
+}
83 183
\ No newline at end of file
... ...
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
32 32
 // You can specify all the values or you can default the Build and Revision Numbers
33 33
 // by using the '*' as shown below:
34 34
 // [assembly: AssemblyVersion("1.0.*")]
35
-[assembly: AssemblyVersion("1.0.0.0")]
36
-[assembly: AssemblyFileVersion("1.0.0.0")]
35
+[assembly: AssemblyVersion("1.1.0.0")]
36
+[assembly: AssemblyFileVersion("1.1.0.0")]
37 37
new file mode 100644
... ...
@@ -0,0 +1,115 @@
1
+using Microsoft.Win32;
2
+using System;
3
+using System.Diagnostics;
4
+using System.Runtime.InteropServices;
5
+using System.Security.Principal;
6
+
7
+namespace JpegDivider
8
+{
9
+    public static class UacHelper
10
+    {
11
+        private const string uacRegistryKey = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
12
+        private const string uacRegistryValue = "EnableLUA";
13
+
14
+        private static uint STANDARD_RIGHTS_READ = 0x00020000;
15
+        private static uint TOKEN_QUERY = 0x0008;
16
+        private static uint TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
17
+
18
+        [DllImport("advapi32.dll", SetLastError = true)]
19
+        [return: MarshalAs(UnmanagedType.Bool)]
20
+        static extern bool OpenProcessToken(IntPtr ProcessHandle, UInt32 DesiredAccess, out IntPtr TokenHandle);
21
+
22
+        [DllImport("advapi32.dll", SetLastError = true)]
23
+        public static extern bool GetTokenInformation(IntPtr TokenHandle, TOKEN_INFORMATION_CLASS TokenInformationClass, IntPtr TokenInformation, uint TokenInformationLength, out uint ReturnLength);
24
+
25
+        public enum TOKEN_INFORMATION_CLASS
26
+        {
27
+            TokenUser = 1,
28
+            TokenGroups,
29
+            TokenPrivileges,
30
+            TokenOwner,
31
+            TokenPrimaryGroup,
32
+            TokenDefaultDacl,
33
+            TokenSource,
34
+            TokenType,
35
+            TokenImpersonationLevel,
36
+            TokenStatistics,
37
+            TokenRestrictedSids,
38
+            TokenSessionId,
39
+            TokenGroupsAndPrivileges,
40
+            TokenSessionReference,
41
+            TokenSandBoxInert,
42
+            TokenAuditPolicy,
43
+            TokenOrigin,
44
+            TokenElevationType,
45
+            TokenLinkedToken,
46
+            TokenElevation,
47
+            TokenHasRestrictions,
48
+            TokenAccessInformation,
49
+            TokenVirtualizationAllowed,
50
+            TokenVirtualizationEnabled,
51
+            TokenIntegrityLevel,
52
+            TokenUIAccess,
53
+            TokenMandatoryPolicy,
54
+            TokenLogonSid,
55
+            MaxTokenInfoClass
56
+        }
57
+
58
+        public enum TOKEN_ELEVATION_TYPE
59
+        {
60
+            TokenElevationTypeDefault = 1,
61
+            TokenElevationTypeFull,
62
+            TokenElevationTypeLimited
63
+        }
64
+
65
+        public static bool IsUacEnabled
66
+        {
67
+            get
68
+            {
69
+                RegistryKey uacKey = Registry.LocalMachine.OpenSubKey(uacRegistryKey, false);
70
+                bool result = uacKey.GetValue(uacRegistryValue).Equals(1);
71
+                return result;
72
+            }
73
+        }
74
+
75
+        public static bool IsProcessElevated
76
+        {
77
+            get
78
+            {
79
+                if (IsUacEnabled)
80
+                {
81
+                    IntPtr tokenHandle;
82
+                    if (!OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_READ, out tokenHandle))
83
+                    {
84
+                        throw new ApplicationException("Could not get process token.  Win32 Error Code: " + Marshal.GetLastWin32Error());
85
+                    }
86
+
87
+                    TOKEN_ELEVATION_TYPE elevationResult = TOKEN_ELEVATION_TYPE.TokenElevationTypeDefault;
88
+
89
+                    int elevationResultSize = Marshal.SizeOf((int)elevationResult);
90
+                    uint returnedSize = 0;
91
+                    IntPtr elevationTypePtr = Marshal.AllocHGlobal(elevationResultSize);
92
+
93
+                    bool success = GetTokenInformation(tokenHandle, TOKEN_INFORMATION_CLASS.TokenElevationType, elevationTypePtr, (uint)elevationResultSize, out returnedSize);
94
+                    if (success)
95
+                    {
96
+                        elevationResult = (TOKEN_ELEVATION_TYPE)Marshal.ReadInt32(elevationTypePtr);
97
+                        bool isProcessAdmin = elevationResult == TOKEN_ELEVATION_TYPE.TokenElevationTypeFull;
98
+                        return isProcessAdmin;
99
+                    }
100
+                    else
101
+                    {
102
+                        throw new ApplicationException("Unable to determine the current elevation.");
103
+                    }
104
+                }
105
+                else
106
+                {
107
+                    WindowsIdentity identity = WindowsIdentity.GetCurrent();
108
+                    WindowsPrincipal principal = new WindowsPrincipal(identity);
109
+                    bool result = principal.IsInRole(WindowsBuiltInRole.Administrator);
110
+                    return result;
111
+                }
112
+            }
113
+        }
114
+    }
115
+}
0 116
\ No newline at end of file