How to get a driver list in Windows? - c#

What is the best way to create a list of all locally installed drivers with C# and the .net Framework?
It should work for Vista based Windows versions.
The list should contain:
Name of the driver
Version of the driver
Location of the driver on the HDD.
Any suggestions / help is appreciated.
Till now I have found a wmi query: that points to the right direction.
Win32_PnPSignedDriver class
("Select * from Win32_PnPSignedDriver")

This should get you started:
SelectQuery query = new System.Management.SelectQuery(
"select name, pathname from Win32_Service");
using (ManagementObjectSearcher searcher =
new System.Management.ManagementObjectSearcher(query))
{
foreach (ManagementObject service in searcher.Get())
{
Console.WriteLine(string.Format(
"Name: {0}\tPath : {1}", service["Name"], service["pathname"]));
}
}

To get a list of drivers use the powershell script:
Get-WmiObject -Class "Win32_PnPSignedDriver" | Select Caption, Description, DeviceID, DeviceClass, DriverVersion, DriverDate, DriverProviderName, InfName
To get a list of driver paths use the powershell script:
Get-WmiObject -Class "Win32_PnPSignedDriverCIMDataFile" | Select Dependent| foreach {
$y = $_ -match '(?<=")(.*?)(?=")'
$Matches[0]
}
At the moment i am just not sure if there are other drivers that this query doesn't match.
To use Powershell in C# use: System.Management.Automation

Related

How do I create this query in C#

I am trying to perform this same WMI query from a C# function.
PS> Get-WMIObject - Namespace root/cimv2/mdm/dmmap - Class MDM_DevDetail_Ext01 - Filter "InstanceID='Ext' AND ParentID='./DevDetail'"
This is the C# code but I get an exception 'Invalid query'
What is the correct way to perform this same query in C#?
ManagementScope scope = new ManagementScope(#"\\localhost\root\cimv2\mdm\dmmap");
scope.Connect();
//Query system for hardware information
ObjectQuery query = new ObjectQuery(
"SELECT * FROM meta_class where __class = 'MDM_DevDetail_Ext01'
and InstanceID='Ext' and ParentID='./DevDetail'");
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query))

how to identify query statement has a subquery in it?

Developing an C# project for SQL Training and giving different exercises based on training on each topic. One of the exercise is to write a query using Sub-Query. which needs to be evaluated whether the user has used/implemented Sub query in the Query Statment.
Q: Write a sql query to show the SalesOrderID,LineTotal,average LineTotal from the Sales.SalesOrderDetail table using Sub query
Select SalesOrderID,LineTotal [LineTotal],
(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal]
from Sales.SalesOrderDetail
[AverageLineTotal] is an sub query.
Can we identify it by any means?? like execution plan Or SP to identify it has an sub query in the statement
Is there any way to identify it through execution Plans??
If this is a c# project you can parse the query with regex to find if the query contains (select {any other text}).
public static void Main()
{
var sql = #"Select SalesOrderID,LineTotal [LineTotal],(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal] from Sales.SalesOrderDetail";
Console.WriteLine(DoesSqlContainSubquery(sql));
}
public bool DoesSqlContainSubquery(string sql)
{
var regexTest = new Regex(#"\( *Select .*\)", RegexOptions.IgnoreCase);
var containsSubquery = regexTest.IsMatch(sql);
return containsSubquery;
}
Parsing ad-hoc scripts is inherently complex due to the plethora T-SQL constructs and options. That being said, a robust method for targeted use cases is parsing scripts with the Microsoft.SqlServer.TransactSql.ScriptDom.
Below is an example PowerShell script that uses the script DOM assembly from the official Microsoft Dacfx NuGet package, downloading and extracting it if needed.
# Add TSqlScript DOM assembly reference, downloading and extracting to the specified location if needed
$scriptDomAssemblyPath = "C:\Temp\Microsoft.SqlServer.TransactSql.ScriptDom.dll"
$scriptDomNuGetUrl = "https://www.nuget.org/api/v2/package/Microsoft.SqlServer.DacFx.x64/150.4384.2"
if(![System.IO.File]::Exists($scriptDomAssemblyPath)) {
$response = Invoke-WebRequest -Uri $scriptDomNuGetUrl
if ($response.StatusCode -ne 200) {
throw "Unable to download Microsoft.SqlServer.TransactSql.ScriptDom NuGet package: $response.StatusCode : $response.StatusDescription"
}
$tempZipFilePath = "$([System.IO.Path]::GetTempPath())/$([System.IO.Path]::GetRandomFileName()).zip"
[System.IO.File]::WriteAllBytes($tempZipFilePath, $response.Content)
$response.BaseResponse.Dispose()
$tempUnzipFolderPath = "$([System.IO.Path]::GetTempPath())/$([System.IO.Path]::GetRandomFileName())"
Expand-Archive -Path $tempZipFilePath -DestinationPath $tempUnzipFolderPath
$tempZipFilePath | Remove-Item
Move-Item "$tempUnzipFolderPath\lib\net46\Microsoft.SqlServer.TransactSql.ScriptDom.dll" "$scriptDomAssemblyPath"
$tempUnzipFolderPath | Remove-Item -Recurse
}
Add-Type -Path $scriptDomAssemblyPath
# script to be parsed
$scriptText = #"
Select SalesOrderID,LineTotal [LineTotal],
(Select AVG(LineTotal) from Sales.SalesOrderDetail) as [AverageLineTotal]
from Sales.SalesOrderDetail
"#
#parse script
$parser = New-Object Microsoft.SqlServer.TransactSql.ScriptDom.TSql150Parser($true)
$parseErrors = New-Object System.Collections.Generic.List[Microsoft.SqlServer.TransactSql.ScriptDom.ParseError]
$scriptReader = New-Object System.IO.StringReader($scriptText)
$script = $parser.Parse($scriptReader, [ref]$parseErrors)
if($parseErrors.Count -gt 0) {
throw "$($parseErrors.Count) parsing errors"
}
# sanity check for expected SELECT query
if(($script.Batches.Count -ne 1) -or ($script.Batches[0].Statements.Count -ne 1) -or ($script.Batches[0].Statements[0].QueryExpression -eq $null)) {
throw "script with single SELECT statement expected"
}
# find scalar subquery expression in select list
$subQueryFound = $false
foreach($selectElement in $script.Batches[0].Statements[0].QueryExpression.SelectElements) {
if($selectElement.Expression.ToString() -eq "Microsoft.SqlServer.TransactSql.ScriptDom.ScalarSubquery") {
$subQueryFound = $true
break
}
}
# show if subquery was used
if($subQueryFound) {
Write-Host "A subquery is used"
}
else {
Write-Host "A subquery is not used"
}

How to execute multi-line powershell command

Trying to execute a PowerShell command in asp.net c# but it returns no results, where am I going wrong?
var shell = PowerShell.Create();
var script = $#"$Groups = Get-ADGroup {groupname}; $members = ForEach ($Group in $Groups) {{Get-AdGroupMember -Identity $Group -Recursive}} ; $members | Get-AdUser -Properties Department | Select-Object Name, Department | Sort Department, Name";
shell.Commands.AddScript(script);
var results = shell.Invoke();
foreach (var psObject in results)
{
dt.Rows.Add(new object[] { psObject.Members["Name"].Value, psObject.Members["Department"].Value });
}
Gridview2.DataSource = dt;
Gridview2.DataBind();
It executes perfectly in PowerShell. Separating the command over lines as per suggested answer does not work.
Edit - I took another look at my powershell and realised that it was unecessarily complicated. I changed it to the below and it now works. Still does not explain why something that returns results in powershell does not work when ran from asp.net.
Get-AdGroupMember -Identity {groupname} -Recursive | Get-AdUser -Properties Department | Select-Object Name, Department | Sort Department, Name

Formatting a WQL Output in C#

I'm trying to build a query, to list all the known computers in SCCM with a specific name.
The query looks like this:
string query = string.Format("Select Name From SMS_R_System Where Name like '" + "%" + computerName + "%" + "'");
If results are found, it puts the result(s) in a dropdown box.
My problem in these case, the output looks like this:
"instance of SMS_R_System{Name = "DC01";};"
But of course, for our use case we only need DC01 as output.
Any tips?
The full Code for the ButtonEvent:
private void ChkBtn_Click(object sender, EventArgs e)
{
string computerName = PCDropDown.Text;
lBox.Items.Clear();
SmsNamedValuesDictionary namedValues = new SmsNamedValuesDictionary();
WqlConnectionManager connection = new WqlConnectionManager(namedValues);
// Connect to remote computer.
try
{
connection.Connect(PrimarySiteServer.ToString());
// Set the query.
string query1 = string.Format("Select Name From SMS_R_System Where Name like '" + "%" + computerName + "%" + "'");
string query2 = string.Format("Select * From SMS_UserMachineRelationship WHERE ResourceName like '" + "%" + computerName + "%" + "' AND IsActive = '1' AND Types = '1'");
// Get the query results
IResultObject queryResults = connection.QueryProcessor.ExecuteQuery(query1);
// Check for results and display in infobox
bool resultsFound = false;
foreach (IResultObject queryResult in queryResults)
{
resultsFound = true;
lBox.Items.Add("Rechner ist vorhanden");
PCDropDown.Items.Add(queryResult.ToString());
}
if (resultsFound == false)
{
lBox.Items.Add("Rechnername nicht gefunden");
}
}
catch
{
MessageBox.Show("No Connection to Config-Manager - Als ZZA ausgeführt? SCCM-Servername richtig?");
}
}
Instead of adding queryResult.ToString() like you do here:
PCDropDown.Items.Add(queryResult.ToString());
you need to add the correct field of queryResult, so in this case:
PCDropDown.Items.Add(queryResult["Name"].StringValue);
Also a quick note. I don't know for who you are writing this and what the next step would be but if this is a read only application that is only used by SCCM Admins I would consider ignoring WMI and going to the SCCM DB via SQL instead. It is a lot faster, SQL has far more powerful options for queries and it does not need the integration of those strange sccm console Dlls (although that is not 100% necessary for WMI either).
If you need write access to create devices or collections etc., or you need to work with the roles the sccm access rights systems implements however WMI is the better or only choice. (And in this case I'd rather really use those strange dlls because all of the MS examples rely on them and it can be hard to translate those tutorials to the vanilla WMI solution C# offers.

Get Active Directory GUID from SQL Server

I'm getting User GUID from Active Directory in C# using the code below:
var GUIDID = "";
using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
{
using (var user = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userNameToUse))
{
if (user != null)
{
GUIDID = user.Guid.ToString();
}
}
}
So the output from the code above for a particular person is:
7b8b17f1-9997-46ac-bec4-c747eed2de33
What I now want to do is query Active Directory from SQL Server 2008 using that GUIDID. However, the issue I'm running into is I don't know the name of the column.
I tried to search for the same person (using their full name) from SQL using the code below:
SELECT cn, objectGUID
FROM 'LDAP://xxx.local/OU=xxx Users,DC=xxx,DC=xxx'
WHERE objectClass = 'User' AND cn = 'John Smith'
Yet, objectGUID, OBjectSID are not the same as the GUIDID my C# code is returning.
I also tried to select * in my SQL query, but it only returns the path.
Any suggestion on how I can find out the GUID COLUMN name from SQL Code?
Thanks
The solution is really simple. I needed to convert the ObjectID
SELECT CONVERT(UNIQUEIDENTIFIER,0xF1178B7B9799AC46BEC4C747EED2DE33);
Hope it helps somebody.

Categories