måndag 12 december 2011

Ini-filer och Powershell

En sak som jag trodde skulle vara trivialt att lösa med Powershell, var att jobba med ini-filer. Det är inte så edge att arbeta med dem men det kan ändå krävas. Jag har grävt lite själv och hittat en lösning som använder WindowsApi för att läsa och skriva i en ini-fil.
Trist nog har jag inte kvar länken till artikeln som jag kopierade. Funktionerna som läser och skriver från och till ini-filer. Skriptet kan verka överdrivet för att endast läsa ini-filer men de fungerar bra. Jag provade själv med några sök och ersätt funktioner men i större miljöer är det väldigt plågsamt att inte ha en ytterst exakt lösning.

De är tre funktioner i skriptet.
  1. Invoke-WindowsApi
    Som namnet säger så sköter denna funktion anropen mot Windows-api och i detta skript anropas av dom andra två Read-ini och write-ini funktionerna.
     
  2. Write-ini
    Skriver till ini-filer.
    Parametrar: Fil, kategori, nyckel, värde
    ex:
    Write-Ini "C:\Windows\win.ini" "Min sektion" "Test" "Värdet"
  3. Read-ini
    Läser ini-filer.
    Parametrar: Fil, kategori, nyckel
    Ex:
    Read-ini "C:\Windows\win.ini" "Min sektion" "Test"

Lycka till!
------Skript nedan------

Function Invoke-WindowsApi {
param(
    [string] $dllName, 
    [Type] $returnType, 
    [string] $methodName,
    [Type[]] $parameterTypes,
    [Object[]] $parameters
    )
$domain = [AppDomain]::CurrentDomain
$name = New-Object Reflection.AssemblyName 'PInvokeAssembly'
$assembly = $domain.DefineDynamicAssembly($name, 'Run')
$module = $assembly.DefineDynamicModule('PInvokeModule')
$type = $module.DefineType('PInvokeType', "Public,BeforeFieldInit")
$inputParameters = @()
$refParameters = @()
for($counter = 1; $counter -le $parameterTypes.Length; $counter++)
{
   if($parameterTypes[$counter - 1] -eq [Ref])
   {
      $refParameters += $counter
      $parameterTypes[$counter - 1] = 
         $parameters[$counter - 1].Value.GetType().MakeByRefType()
      $inputParameters += $parameters[$counter - 1].Value
   }
   else
   {
      $inputParameters += $parameters[$counter - 1]
   }
}
$method = $type.DefineMethod($methodName, 'Public,HideBySig,Static,PinvokeImpl',
    $returnType, $parameterTypes)
foreach($refParameter in $refParameters)
{
   [void] $method.DefineParameter($refParameter, "Out", $null)
}
$ctor = [Runtime.InteropServices.DllImportAttribute].GetConstructor([string])
$attr = New-Object Reflection.Emit.CustomAttributeBuilder $ctor, $dllName
$method.SetCustomAttribute($attr)
$realType = $type.CreateType()
$realType.InvokeMember($methodName, 'Public,Static,InvokeMethod', $null, $null, 
    $inputParameters)
foreach($refParameter in $refParameters)
{
   $parameters[$refParameter - 1].Value = $inputParameters[$refParameter - 1]
}
}

Function Read-Ini {
param(
    $file,
    $category,
    $key)
$returnValue = New-Object System.Text.StringBuilder 500
$parameterTypes = [string], [string], [string], [System.Text.StringBuilder], [int], [string]
$parameters = [string] $category, [string] $key, [string] "",
   [System.Text.StringBuilder] $returnValue, [int] $returnValue.Capacity, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "GetPrivateProfileString" $parameterTypes $parameters)
$returnValue.ToString()
}

Function Write-Ini {
param(
    $file,
    $category,
    $key,
    $value)
$parameterTypes = [string], [string], [string], [string]
$parameters = [string] $category, [string] $key, [string] $value, [string] $file
[void] (Invoke-WindowsApi "kernel32.dll" ([UInt32]) "WritePrivateProfileString" $parameterTypes $parameters)
}

Inga kommentarer:

Skicka en kommentar