ScpControl/Driver/PNPUtilLib/PNPUtil.cs (201 lines of code) (raw):
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using log4net;
/***
* Change log:
* ------------------
* Dec 30, 2012 : Merged in user submitted patch (ID: 10344) to support non-English builds. Thanks jenda__.
*
*/
namespace ScpControl.Driver.PNPUtilLib
{
public class PnpUtil : IDriverStore
{
private static readonly ILog Log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static bool PnpUtilHelper(PnpUtilOptions option, string infName, ref string output)
{
var retVal = true;
var fDebugPrintOutput = false;
//
// Setup the process with the ProcessStartInfo class.
//
var start = new ProcessStartInfo
{
FileName = @"pnputil.exe" /* exe name.*/,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
switch (option)
{
//
// [jenda_] I also had problems with some arguments starting "-". "/" works fine
//
case PnpUtilOptions.Enumerate:
start.Arguments = @"/e";
break;
case PnpUtilOptions.Delete:
start.Arguments = @"/d " + infName;
break;
case PnpUtilOptions.ForceDelete:
start.Arguments = @"/f /d " + infName;
break;
case PnpUtilOptions.Add:
fDebugPrintOutput = true;
start.WorkingDirectory = Path.GetDirectoryName(infName);
start.Arguments = @"/a " + Path.GetFileName(infName);
Log.DebugFormat("[Add] workDir = {0}, arguments = {1}", start.WorkingDirectory,
start.Arguments);
break;
case PnpUtilOptions.AddInstall:
fDebugPrintOutput = true;
start.WorkingDirectory = Path.GetDirectoryName(infName);
start.Arguments = @"/i /a " + Path.GetFileName(infName);
Log.DebugFormat("[AddInstall] workDir = {0}, arguments = {1}", start.WorkingDirectory,
start.Arguments);
break;
}
//
// Start the process.
//
var result = "";
try
{
using (var process = Process.Start(start))
{
//
// Read in all the text from the process with the StreamReader.
//
using (var reader = process.StandardOutput)
{
result = reader.ReadToEnd();
output = result;
if (fDebugPrintOutput)
Log.DebugFormat("[Result_start] ---- {0}{1}[----- Result_End]{0}", Environment.NewLine,
result);
if (option == PnpUtilOptions.Delete || option == PnpUtilOptions.ForceDelete)
{
// [jenda_] Really don't know, how to recognize error without language-specific string recognition :(
// [jenda_] But those errors should contain ":"
if (output.Contains(@":")) //"Deleting the driver package failed"
{
retVal = false;
}
}
if ((option == PnpUtilOptions.Add || option == PnpUtilOptions.AddInstall))
{
/* [jenda_]
This regex should recognize (~) this pattern:
* MS PnP blah blah
*
* blah blah blah
* blah blah (...)
*
* blah blah: *number*
* blah blah blah: *number*
*
*/
var MatchResult = Regex.Match(output, @".+: +([0-9]+)[\r\n].+: +([0-9]+)[\r\n ]+",
RegexOptions.Singleline);
if (MatchResult.Success) // [jenda_] regex recognized successfully
{
// [jenda_] if trying to add "0" packages or if number packages and number added packages differs
if (MatchResult.Groups[1].Value == "0" ||
MatchResult.Groups[1].Value != MatchResult.Groups[2].Value)
{
Log.ErrorFormat("[Error] failed to add " + infName);
retVal = false;
}
}
else
{
Log.ErrorFormat("[Error] unknown response while trying to add " + infName);
retVal = false;
}
}
}
}
}
catch (Exception e)
{
// dont catch all exceptions -- but will do for our needs!
Log.ErrorFormat(@"{0}\n{1}" + Environment.NewLine, e.Message, e.StackTrace);
output = "";
retVal = false;
}
return retVal;
}
private enum PnpUtilOptions
{
Enumerate,
Delete,
ForceDelete,
Add,
AddInstall
};
#region IDriverStore Members
public List<DriverStoreEntry> EnumeratePackages()
{
var ldse = new List<DriverStoreEntry>();
var output = "";
var result = PnpUtilHelper(PnpUtilOptions.Enumerate, "", ref output);
if (result)
{
// Trace.TraceInformation("O/P of Enumeration : " + Environment.NewLine + output + Environment.NewLine);
// Parse the output
// [jenda_] Didn't work on non-english Windows - changed from string recognition to counting lines
using (var sr = new StringReader(output))
{
var currentLine = "";
string[] currentLineDivided = {};
var dse = new DriverStoreEntry();
byte lineNum = 0;
while ((currentLine = sr.ReadLine()) != null)
{
currentLineDivided = currentLine.Split(':');
if (currentLineDivided.Length == 2)
{
currentLineDivided[1] = currentLineDivided[1].Trim();
switch (lineNum)
{
case 0: // [jenda_] Published name :
dse.DriverPublishedName = currentLineDivided[1];
break;
case 1: //Driver package provider :
dse.DriverPkgProvider = currentLine.Split(':')[1].Trim();
break;
case 2: // [jenda_] Class :
dse.DriverClass = currentLine.Split(':')[1].Trim();
break;
case 3: // [jenda_] Driver date and version :
var DateAndVersion = currentLine.Split(':')[1].Trim();
// date and version may be empty
if(DateAndVersion.Length > 0)
{
dse.DriverDate = DateAndVersion.Split(' ')[0].Trim();
dse.DriverVersion = DateAndVersion.Split(' ')[1].Trim();
}
break;
case 4: // [jenda_] Signer name :
dse.DriverSignerName = currentLine.Split(':')[1].Trim();
ldse.Add(dse);
dse = new DriverStoreEntry();
break;
default:
continue;
}
lineNum++;
if (lineNum > 4)
lineNum = 0;
}
}
}
}
return ldse;
}
public bool DeletePackage(DriverStoreEntry dse, bool forceDelete)
{
var dummy = "";
return PnpUtilHelper(forceDelete ? PnpUtilOptions.ForceDelete : PnpUtilOptions.Delete,
dse.DriverPublishedName,
ref dummy);
}
public bool AddPackage(string infFullPath, bool install)
{
var dummy = "";
return PnpUtilHelper(install ? PnpUtilOptions.AddInstall : PnpUtilOptions.Add,
infFullPath, ref dummy);
}
#endregion
}
}