The latest build that I know about is DAO.DBEngine.120.
Its a bit tricky to write in powershell. Below is the code just in case anyone is looking for it:
$iret = [System.Reflection.Assembly]::LoadWithPartialName("System.Management")
$mc = new-object System.Management.ManagementClass
$mc.Path.NamespacePath = "root\cimv2"
$mc.Path.ClassName = "Win32_Process";
$mc.Scope.Options.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy;
$mc.Scope.Options.Impersonation = [System.Management.ImpersonationLevel]::Impersonate;
$moc = $mc.GetInstances()
$DBEngine = new-Object -comobject DAO.DBEngine.120
$DBEngine.CreateDatabase("C:\Melody.mdb", ";LANGID=0x0409;CP=1252;COUNTRY=0", 64)
$db = $DBEngine.OpenDatabase("C:\Melody.mdb", $false, $false, "")
$rs = $db.OpenRecordset("Properties");
foreach($mo in $moc)
{
$rs.AddNew()
$x=0
$Fields = $rs.GetType().InvokeMember("Fields", [System.Reflection.BindingFlags]::GetProperty, $null, $rs, $null)
foreach($Field in $Fields)
{
[System.String] $Name = $Field.Name
[System.String] $Value = $mo.Properties.Item($Name).Value
$Field.Value = $Value
}
$x=0
$rs.Update()
}
Saturday, April 6, 2013
Create a SQL Database using Powershell and SQLClient
First, I am by far no expert when it comes to knowing all the ins and outs of SQL Server. What I do know is this, you can create a database, create and populate a table and then render the information in a variety of ways using Powershell.
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.SqlClient.SqlConnection
$con.ConnectionString="Data Source=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.SqlClient.SqlCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
You can do the same thing with Odbc and OleDb as well.
Here's the OleDb example:
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.OleDb.OleDbConnection
$con.ConnectionString="Provider=SQLOLEDB;Data Source=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.OleDb.OleDbCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
And when using Odbc:
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.Odbc.OdbcConnection
$con.ConnectionString="Driver={SQL Server};Server=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.Odbc.OdbcCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
Tomorrow, I'll show you how to create and populate the table.
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.SqlClient.SqlConnection
$con.ConnectionString="Data Source=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.SqlClient.SqlCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
You can do the same thing with Odbc and OleDb as well.
Here's the OleDb example:
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.OleDb.OleDbConnection
$con.ConnectionString="Provider=SQLOLEDB;Data Source=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.OleDb.OleDbCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
And when using Odbc:
$iret = [System.Reflection.Assembly]::loadWithPartialName("System.Data")
$con = new-object System.Data.Odbc.OdbcConnection
$con.ConnectionString="Driver={SQL Server};Server=.;Integrated Security=sspi;"
$con.Open()
$cmd = new-object System.Data.Odbc.OdbcCommand()
$cmd.Connection = $con
$cmd.CommandType = [System.Data.CommandType]::Text
$cmd.CommandText = "CREATE Database DataOne"
$cmd.ExecuteNonQuery
Tomorrow, I'll show you how to create and populate the table.
Friday, April 5, 2013
To Text Or Not To Text -- I just want to be in control
If you are like me -- another programmer forced to learn Powershell -- you want to be in control of the output. What output format it is in and just how easy it is two read comes quickly to mind.
With that thought in mind, I decided to see if I could get the textwriter to work for me.
I did this by using the following code:
[System.IO.TextWriter]$txtstream = new-object System.IO.Streamwriter([System.Environment]::CurrentDirectory + "\WillItWork.txt")
That worked perfectly fine. To close this object out:
$txtstream.Flush()
$txtstream.Close()
$txtstream = $null
The programer's mindset text formats include: csv, excel spreadsheets, hta, html, attribute xml, element xml, element xml for xsl, and xsl -- just to name a few. Some of these can also be put into different formats such as Single and multi line horizontal and vertical views as well as the text being formatted for a more table like view of the data.
Please use the 32 bit version of Powershell for the following code as the code will fail in the 64 bit version. Jet is not supported in the 64 bit world.
$con = new-object -comobject ADODB.Connection
$con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\nwind.mdb")
$rs = new-object -comobject ADODB.Recordset
$rs.ActiveConnection = $con
$rs.CursorLocation = [ADODB.CursorLocationEnum]::adUseClient
$rs.LockType = [ADODB.LockTypeEnum]::adLockOptimistic
$rs.let_Source("Select * From Products")
$rs.Open()
Now that I have an open recordset, I want to do something with the information. So, I'm going to create some xml:
[System.IO.TextWriter]$txtstream = new-object System.IO.Streamwriter([System.Environment]::CurrentDirectory + "\product.xml")
$con = new-object -comobject ADODB.Connection
$con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\nwind.mdb")
$rs = new-object -comobject ADODB.Recordset
$rs.ActiveConnection = $con
$rs.CursorLocation = [ADODB.CursorLocationEnum]::adUseClient
$rs.LockType = [ADODB.LockTypeEnum]::adLockOptimistic
$rs.let_Source("Select * From Products")
$rs.Open()
$txtstream.WriteLine("<?xml version='1.0' encoding='iso-8859-1'?>")
$txtstream.WriteLine("<data>")
$txtstream.WriteLine("<Products>")
$rs.MoveFirst();
for($y=0;$y -lt $rs.RecordCount;$y++)
{
$txtstream.WriteLine("<Product>")
for($x=0;$x -lt $rs.Fields.Count;$x++)
{
$fld = $rs.Fields[$x]
$Name = $fld.GetType().InvokeMember("Name", [System.Reflection.BindingFlags]::GetProperty, $null, $fld, $null)
$Value = $fld.GetType().InvokeMember("Value", [System.Reflection.BindingFlags]::GetProperty, $null, $fld, $null)
$txtstream.WriteLine("<" + $Name + "><![CDATA[" + $Value + "]]></" + $Name + ">")
}
$txtstream.WriteLine("</Product>")
$rs.MoveNext()
}
$txtstream.WriteLine("</Products>")
$txtstream.WriteLine("</data>")
$txtstream.Flush()
$txtstream.Close()
$txtstream = $null
With that thought in mind, I decided to see if I could get the textwriter to work for me.
I did this by using the following code:
[System.IO.TextWriter]$txtstream = new-object System.IO.Streamwriter([System.Environment]::CurrentDirectory + "\WillItWork.txt")
That worked perfectly fine. To close this object out:
$txtstream.Flush()
$txtstream.Close()
$txtstream = $null
The programer's mindset text formats include: csv, excel spreadsheets, hta, html, attribute xml, element xml, element xml for xsl, and xsl -- just to name a few. Some of these can also be put into different formats such as Single and multi line horizontal and vertical views as well as the text being formatted for a more table like view of the data.
Please use the 32 bit version of Powershell for the following code as the code will fail in the 64 bit version. Jet is not supported in the 64 bit world.
$con = new-object -comobject ADODB.Connection
$con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\nwind.mdb")
$rs = new-object -comobject ADODB.Recordset
$rs.ActiveConnection = $con
$rs.CursorLocation = [ADODB.CursorLocationEnum]::adUseClient
$rs.LockType = [ADODB.LockTypeEnum]::adLockOptimistic
$rs.let_Source("Select * From Products")
$rs.Open()
Now that I have an open recordset, I want to do something with the information. So, I'm going to create some xml:
[System.IO.TextWriter]$txtstream = new-object System.IO.Streamwriter([System.Environment]::CurrentDirectory + "\product.xml")
$con = new-object -comobject ADODB.Connection
$con.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\nwind.mdb")
$rs = new-object -comobject ADODB.Recordset
$rs.ActiveConnection = $con
$rs.CursorLocation = [ADODB.CursorLocationEnum]::adUseClient
$rs.LockType = [ADODB.LockTypeEnum]::adLockOptimistic
$rs.let_Source("Select * From Products")
$rs.Open()
$txtstream.WriteLine("<?xml version='1.0' encoding='iso-8859-1'?>")
$txtstream.WriteLine("<data>")
$txtstream.WriteLine("<Products>")
$rs.MoveFirst();
for($y=0;$y -lt $rs.RecordCount;$y++)
{
$txtstream.WriteLine("<Product>")
for($x=0;$x -lt $rs.Fields.Count;$x++)
{
$fld = $rs.Fields[$x]
$Name = $fld.GetType().InvokeMember("Name", [System.Reflection.BindingFlags]::GetProperty, $null, $fld, $null)
$Value = $fld.GetType().InvokeMember("Value", [System.Reflection.BindingFlags]::GetProperty, $null, $fld, $null)
$txtstream.WriteLine("<" + $Name + "><![CDATA[" + $Value + "]]></" + $Name + ">")
}
$txtstream.WriteLine("</Product>")
$rs.MoveNext()
}
$txtstream.WriteLine("</Products>")
$txtstream.WriteLine("</data>")
$txtstream.Flush()
$txtstream.Close()
$txtstream = $null
Wednesday, April 3, 2013
Get-WMIObject To be or not to be -- a collection or an object
Consider this code:
$mystr = ""
$ws = new-object -comobject WScript.Shell
$path = $ws.CurrentDirectory + "\Win32_Process.csv"
$fso = new-object -comobject Scripting.FileSystemObject
$txtstream = $fso.OpenTextFile($path, 2, $true, -2)
$moc = Get-WMIObject -namespace root\cimv2 -class Win32_Process
$mocEnum = $moc.GetType().InvokeMember('GetEnumerator', 'InvokeMethod',$Null, $moc, $Null)
while($mocEnum.MoveNext())
{
$obj = $mocEnum.Current
foreach($prop in $obj.Properties)
{
if($mystr -ne "")
{
$mystr += ","
}
$mystr += $prop.Name
}
$txtstream.WriteLine($mystr)
$mystr = ""
break
}
$mocEnum.Reset()
while($mocEnum.MoveNext())
{
$obj = $mocEnum.Current
foreach($prop in $obj.Properties)
{
if($mystr -ne "")
{
$mystr += ","
}
$tstr = '"'
$tstr += $prop.value
$tstr += '"'
$mystr += $tstr
}
$txtstream.WriteLine($mystr)
$mystr = ""
}
As it stands, this code works well to create a csv file. And, yes, you can do the same using the PSObject. The problem is, the code assumes the Get-WMIObject will return a collection of objects and in some cases it will not.
Exception calling "InvokeMember" with "5" argument(s): "Method 'System.Management.ManagementObject.GetEnumerator' not found."
At C:\Users\Administrator\Desktop\Test.ps1:2 char:39
+ $mocEnum = $moc.GetType().InvokeMember <<<< ('GetEnumerator', 'InvokeMethod',$Null, $moc, $Null)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
You cannot call a method on a null-valued expression.
At C:\Users\Administrator\Desktop\Test.ps1:3 char:24
+ while($mocEnum.MoveNext <<<< ())
+ CategoryInfo : InvalidOperation: (MoveNext:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
And, by the way, the code works fine using foreach enumerations of the objects.
Powershell: Learning something new everyday
Learning something new everyday is what makes programming interesting. The lesson learned today is to stop thinking powershell is "just like any other language". Because it is not.
Consider the following:
My task is to check the local registry for the version of the OS. So, in line, I did the following to check it:
PS C:\Users\Administrator> $HKEY_LOCAL_MACHINE = 2147483650
PS C:\Users\Administrator> $Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
PS C:\Users\Administrator> $Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
PS C:\Users\Administrator> $Result = $Reg.GetStringValue($HKEY_LOCAL_MACHINE, $Key, "CurrentVersion")
PS C:\Users\Administrator> write-host $Result
System.Management.ManagementBaseObject
PS C:\Users\Administrator> $Result.GetText(0)
instance of __PARAMETERS
{
ReturnValue = 0;
sValue = "6.1";
};
Okay, everything looks good. In line, that is. What happens when you want to put the routine into a function and call it anywhere.
Well, it turns out, you can try, but you'll be wasting a lot of hours.
First, let's create the function wrapper:
function get_operatingsystem_version()
{
}
Now, you would think, if you've been programming for as long as I have, that you would od the following:
$HKLM = 2147483650
$Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
$Version = get_operatingsystem_version
if ($Version -ne "Error")
{
write-host $version
}
function get_operatingsystem_version()
{
$Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Result = $Reg.GetStringValue($HKLM, $Key, "CurrentVersion")
if($Result.ReturnValue -eq 0)
{
return $Result.sValue
}
else
{
return "Error"
}
}
Should work, right? Doesn't. In fact, it comes back with the following error:
The term 'get_operatingsystem_version' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\Administrator\Desktop\GetOS.ps1:5 char:39
+ $Version = get_operatingsystem_version <<<<
+ CategoryInfo : ObjectNotFound: (get_operatingsystem_version:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:\Users\Administrator>
Why did this happen? Because the function has not yet been seen by Powershell at the point where the call is being made.
Now, let's try it this way:
$HKLM = 2147483650
$Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
function get_operatingsystem_version()
{
$Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Result = $Reg.GetStringValue($HKLM, $Key, "CurrentVersion")
if($Result.ReturnValue -eq 0)
{
return $Result.sValue
}
else
{
return "Error"
}
}
$Version = get_operatingsystem_version
if ($Version -ne "Error")
{
write-host $version
}
When I run this, I get:
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\GetOS.ps1
6.1
Consider the following:
My task is to check the local registry for the version of the OS. So, in line, I did the following to check it:
PS C:\Users\Administrator> $HKEY_LOCAL_MACHINE = 2147483650
PS C:\Users\Administrator> $Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
PS C:\Users\Administrator> $Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
PS C:\Users\Administrator> $Result = $Reg.GetStringValue($HKEY_LOCAL_MACHINE, $Key, "CurrentVersion")
PS C:\Users\Administrator> write-host $Result
System.Management.ManagementBaseObject
PS C:\Users\Administrator> $Result.GetText(0)
instance of __PARAMETERS
{
ReturnValue = 0;
sValue = "6.1";
};
Okay, everything looks good. In line, that is. What happens when you want to put the routine into a function and call it anywhere.
Well, it turns out, you can try, but you'll be wasting a lot of hours.
First, let's create the function wrapper:
function get_operatingsystem_version()
{
}
Now, you would think, if you've been programming for as long as I have, that you would od the following:
$HKLM = 2147483650
$Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
$Version = get_operatingsystem_version
if ($Version -ne "Error")
{
write-host $version
}
function get_operatingsystem_version()
{
$Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Result = $Reg.GetStringValue($HKLM, $Key, "CurrentVersion")
if($Result.ReturnValue -eq 0)
{
return $Result.sValue
}
else
{
return "Error"
}
}
Should work, right? Doesn't. In fact, it comes back with the following error:
The term 'get_operatingsystem_version' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\Administrator\Desktop\GetOS.ps1:5 char:39
+ $Version = get_operatingsystem_version <<<<
+ CategoryInfo : ObjectNotFound: (get_operatingsystem_version:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
PS C:\Users\Administrator>
Why did this happen? Because the function has not yet been seen by Powershell at the point where the call is being made.
Now, let's try it this way:
$HKLM = 2147483650
$Key = "SOFTWARE\Microsoft\Windows NT\CurrentVersion"
function get_operatingsystem_version()
{
$Reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Result = $Reg.GetStringValue($HKLM, $Key, "CurrentVersion")
if($Result.ReturnValue -eq 0)
{
return $Result.sValue
}
else
{
return "Error"
}
}
$Version = get_operatingsystem_version
if ($Version -ne "Error")
{
write-host $version
}
When I run this, I get:
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\GetOS.ps1
6.1
Subscribe to:
Posts (Atom)