[C#] Path & arguments strings
-
mardi 24 avril 2012 11:28
Hi everybody,
Looking for uninstall strings in Registry (Path=HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall, Key=UninstallString), I've found some 'bad' pathes on Adobe Products (reported as Bug 3172314 : [url]https://bugbase.adobe.com/index.cfm?event=bug&id=3172314[/url]).
I think this is not the only product affected.
Here are some VALID pathes found (for me) :
---------------------------------------------------------
MsiExec.exe /I{8C6D6116-B724-4810-8F2D-D047E6B7D68E}
"C:\Program Files\Common Files\Microsoft Shared\OFFICE14\Oarpmany.exe" /removereleaseinpatch "{90140000-001F-0401-0000-0000000FF1CE}" "1036" "0"
"C:\Program Files\7-Zip\Uninstall.exe"
"C:\Program Files\Easeware\DriverEasy\unins000.exe" /SILENTHere are some INVALID pathes found (for me) :
------------------------------------------------------------
c:\Program Files\Common Files\Adobe AIR\Versions\1.0\Resources\Adobe AIR Updater.exe -arp:uninstallIn this last case, string parser will find :
Arg0 = c:\Program
Arg1 = Files\Common[...]The only way I found is to parse and combine each argument while is exist on drive but it looks like too piggy code.
So, what's the best way to get
Arg0 = c:\Program Files\Common Files\Adobe AIR\Versions\1.0\Resources\Adobe AIR Updater.exe
Arg1 = -arp:uninstallThanks,
Vincent
Toutes les réponses
-
mardi 24 avril 2012 13:37what are the classes and methods you are using, that leads to this behaviour ?
-
mercredi 25 avril 2012 11:33Modérateur
Hi Vincent,
Welcome to the MSDN Forum.
Based on your reference, it seems that the Adobe doesn't write the double quotes signal into the register. As an end user - you, in my opinion, cannot change the behavior of Adobe program, so I think you can splice the arguments until you got an arguments contains ".exe"
For example:
string path = ""; foreach (string s in args) { path += s; if (s.ToLower().Contains(".exe") == true) { break; // TODO: might not be correct. Was : Exit For } }
you can get the correct path by this way.
I hope this will be helpful.
Best regards,
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- Marqué comme réponse Duvernet Vincent mercredi 25 avril 2012 21:57
- Modifié Mike FengMicrosoft Contingent Staff, Moderator jeudi 26 avril 2012 02:55 Modify the code
-
mercredi 25 avril 2012 14:15
I'm using standard registry methods :
RegistryKey RootKey = Registry.LocalMachine;
string strPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + options.Guid;
RegistryKey CurrentKey = RootKey.OpenSubKey(strPath, false);
if (CurrentKey != null)
{
string strUninstallString = CurrentKey.GetValue("UninstallString").ToString ();
[...]
Process.Start ();
}I think you're on the way but we can't be sure file is .EXE instead of .CMD, .BAT, .COM...
And the executable may not contain file extension. So tomorrow, this string will (still) be correct for Adobe product ?
"c:\Program Files\Common Files\Adobe AIR\Versions\1.0\Resources\Adobe AIR Updater"
-
mercredi 25 avril 2012 17:46
For generic case (so we exclude Adobe vision of path... :/), we can have the expecting result using Regex :
static string[] CheckPath(string bufferToManage)
{
string strTrimBuffer = bufferToManage.Trim();
string[] Result = null;
string pattern = " (?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))";
Regex r = new Regex(pattern);
string[] sites = r.Split(strTrimBuffer);
foreach (string s in sites)
{
Console.WriteLine("Arg: <" + s +">");
}
return Result;
} -
mercredi 25 avril 2012 21:57
Hi. I've found the solution using Mike point of view.
In the sample below, we're scanning Registry to get program uninstall string. It seems to work perfectly on my computer :)/// <summary> /// Get full filename and its arguments from a string /// </summary> /// <author>Vincent Duvernet</author> /// <company>Nolmë Informatique</company> /// <web>http://www.nolme.com</web> /// using System; using System.Collections.Generic; using System.Text; using Microsoft.Win32; using System.Text.RegularExpressions; using System.IO; using System.Globalization; /// <summary> /// Main namespace /// </summary> namespace ConsoleApplication1 { class Program { /// <summary> /// Get file presence /// </summary> /// <param name="pathToCheck">Path to check (can contain %VARIABLE%, filename without extension, no path specified, no ~</param> /// <returns>Return the full expanded filename</returns> static string IsFileExist(string pathToCheck) { string strResult = null; // First check : no string manipulation string strPathToCheckTrimmed = pathToCheck.Trim(); if (File.Exists(strPathToCheckTrimmed)) { strResult = strPathToCheckTrimmed; } else { // Second check : expand variables, remove quotes & spaces string strExpandedPath = Environment.ExpandEnvironmentVariables(strPathToCheckTrimmed); string strExpandedPathTrimmed = strExpandedPath.Replace('"', ' ').Trim(); if (File.Exists(strExpandedPathTrimmed)) { strResult = strExpandedPathTrimmed; } else { // Third check : use environment variable string strAllPathes = Environment.GetEnvironmentVariable("PATH"); string strAllPathesExt = Environment.GetEnvironmentVariable("PATHEXT"); string pattern = ";(?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"; Regex r = new Regex(pattern); string[] splittedPathArray = r.Split(strAllPathes); string[] splittedPathExtArray = r.Split(strAllPathesExt); // Loop on all paths for (int i = 0; i < splittedPathArray.Length; i++) { string strTempPath = Path.Combine(splittedPathArray[i], pathToCheck); if (File.Exists(strTempPath)) { // Ok it works ^^, we can stop searching other file instance elsewhere strResult = strTempPath; break; } else { // Fourth check : scan will all file extensions for (int j = 0; j < splittedPathExtArray.Length; j++) { if (File.Exists(strTempPath + splittedPathExtArray[j])) { // Ok it works ^^, we can stop searching other file instance elsewhere strResult = strTempPath + splittedPathExtArray[j]; j = splittedPathExtArray.Length; i = splittedPathArray.Length; } } } } } } // Expand path to remove ~ inside short filename if (strResult != null) { strResult = Path.GetFullPath(strResult); } return strResult; } /// <summary> /// Split a buffer into full filename + arguments /// </summary> /// <param name="bufferToManage">buffer to manage</param> /// <returns>Full filename as arg0 and arguments after. Can be NULL if file don't exist</returns> /// <remarks>Thanks for the article on TechRepublic for RegEx</remarks> /// <remarks>Take care if destination file DON'T EXIST</remarks> /// <see cref="http://www.techrepublic.com/article/easily-parse-string-values-with-net/6030362"/> static string[] CheckPath(string bufferToManage) { string strTrimBuffer = bufferToManage.Trim(); string[] Result = null; string pattern = " (?=(?:[^\"]*\"[^\"]*\")*(?![^\"]*\"))"; Regex r = new Regex(pattern); string[] splittedArray = r.Split(strTrimBuffer); MatchCollection matches = r.Matches(strTrimBuffer); // First part : during split, spaces have been removed, so, add it again int iPosition = 0; for (int i = 0; i < splittedArray.Length; i++) { string strCurrentArgument = splittedArray[i]; if (!strCurrentArgument.EndsWith(@"""")) { if ((iPosition + strCurrentArgument.Length + 1 < strTrimBuffer.Length) && (strTrimBuffer[iPosition + strCurrentArgument.Length] == ' ')) { // Add spaces removed during Regex split splittedArray[i] = strCurrentArgument + " "; } } iPosition += splittedArray[i].Length; } // Loop inside arguments to get the application application full path StringBuilder sb = new StringBuilder(); for (int j = 0; j < splittedArray.Length; j++) { sb.Append(splittedArray [j]); // Expand path, remove double quotes, remove exterior spaces string strExpandedPath = IsFileExist(sb.ToString()); if (strExpandedPath != null) { // Count empty elements (in case of multiple spaces between each argument) int iInvalidArguments = 0; for (int k = 0; k < splittedArray.Length; k++) { splittedArray[k] = splittedArray[k].Trim(); if (String.IsNullOrEmpty (splittedArray[k])) { iInvalidArguments++; } } // File exist, all items remaining are arguments int iNumberOfArguments = splittedArray.Length - (j + 1) - iInvalidArguments; // Create destination buffer Result = new string[iNumberOfArguments + 1]; // Save program full path Result[0] = strExpandedPath; // Save program parameters int iCurrentArgumentOffset = 1; for (int k = 0; k < iNumberOfArguments + iInvalidArguments; k++) { if (!String.IsNullOrEmpty(splittedArray[j + k + 1])) { Result[iCurrentArgumentOffset] = splittedArray[j + k + 1]; iCurrentArgumentOffset++; } } break; } } return Result; } /// <summary> /// Main program entry /// </summary> /// <param name="args"></param> static void Main(string[] args) { // Loop on Registry RegistryKey RootKey = Registry.LocalMachine; string strPath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\"; string[] Result; RegistryKey CurrentKey = RootKey.OpenSubKey(strPath, false); if (CurrentKey != null) { string[] strGuidArray = CurrentKey.GetSubKeyNames(); for (int i = 0; i < strGuidArray.Length; i++) { RegistryKey CurrentProgramKey = CurrentKey.OpenSubKey(strGuidArray[i], false); if (CurrentProgramKey != null) { object RegistryValue = CurrentProgramKey.GetValue("UninstallString"); if (RegistryValue != null) // UninstallString is not always defined { string strUninstallString = RegistryValue.ToString(); if (!String.IsNullOrEmpty(strUninstallString)) { Result = CheckPath(strUninstallString); if (Result != null) { Console.WriteLine("Result n° {0} : {1}", i, strGuidArray[i]); Console.WriteLine("----------------"); for (int j = 0; j < Result.Length; j++) { Console.WriteLine("Arg. {0}: <{1}>", j, Result[j]); } Console.WriteLine(""); } } } } } } Console.WriteLine("Finished"); Console.ReadKey(); } } }
- Marqué comme réponse Duvernet Vincent mercredi 25 avril 2012 21:57
-
jeudi 26 avril 2012 03:06Modérateur
Hi Duvernet,
Congratulations.
Thank you for sharing the whole solution here. It will be useful for the other community members.
Best regards.
Mike Feng
MSDN Community Support | Feedback to us
Please remember to mark the replies as answers if they help and unmark them if they provide no help.

