qshinoの日記

Powershell関係と徒然なこと

C# in powerShell

C# in PowerShell

PowerShell 内でC#を使う。

C#のコードを文字列に格納

$cs = "csharp code..."

Add-Typeコマンドレットでロード

Add-Type $cs

参照アセンブリがある場合は、

C#以外の言語なら、

  • Language <言語名>

言語名にはJSharp, CSharpVersion3, visualbasic, JScript が使用可能。

ロード後は、C#コードが使用可能。

ファイルから

$file=“a.cs” Add-Type $file

$dll = “a.dll” Add-Type $dll

サンプル

Param($name)
$asm = ("System")
$cs = @"
using System;
public static class Salute
    {
        public static void Hi(string name)
        {
            Console.WriteLine("Hi, " + name+ "!");
        }
    }
"@

Add-Type $cs -ReferencedAssemblies $asm
[Salute]::Hi($name)

DLLからの場合

> [Reflection.Assembly]::LoadFile("c:\temp\MyMathLib.dll")
> [MyMathLib.Methods]::Sum(10, 2)

> $mathInstance = new-object MyMathLib.Methods
> $mathInstance.Product(10, 2)

DLLの中は

namespace MyMathLib
{
    public class Methods
    {
        public Methods()
        {
        }

        public static int Sum(int a, int b)
        {
            return a + b;
        }

        public int Product(int a, int b)
        {
            return a * b;
        }
    }
}

アセンブリロードについて

まずはPSVersion

Add-TypeはPowerShell 2.0以降で実装

PowerShell1.0の場合

Add-Typeの問題

Add-Typeは便利だが、複数リビジョンのアセンブリが導入済みの場合、古い方のロードやロードに失敗する。

その場合、フルネームで指定する。

Add-Type -AssemblyName "Microsoft.SqlServer.SMO, Version=11.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"

あるいは Reflection.Assembly::LoadWithPartialName(“Microsoft.SqlServer.Smo”)

アセンブリロード

整理すると、

  1. PS1.0なら、LoadWP 一択。
  2. 2.0以降なら、add-type クラス名で。
  3. エラーなら、LoadWP…
  4. 最後は、Add-Type フルネーム指定

Add-Type書式

4種類の書式がある。

  1. -AssemblyName : アセンブリ名[]
  2. [-Name] クラス名
  3. [-Path] ファイル名[]
  4. [-TypeDefinition] コード文字列

2番以降なら下記オプションでDLL作成可。簡易コンパイラになる。

  • -OutputAssemly DLL名
Add-Type -AssemblyName <string[]> [-IgnoreWarnings] [-PassThru] [<CommonParameters>]

Add-Type [-Name] <string> [-MemberDefinition] <string[]> [-CodeDomProvider <CodeDomProvider>] [-CompilerParameters <CompilerParameters>] [-Language {<CSharp> | <CSharpVersion3> | <VisualBasic> | <JScript>}] [-Namespace <string>] [-OutputAssembly <string>] [-OutputType <OutputAssemblyType>] [-ReferencedAssemblies <string[]>] [-UsingNamespace <string[]>] [-IgnoreWarnings] [-PassThru] [<CommonParameters>]

Add-Type [-Path] <string[]> [-CompilerParameters <CompilerParameters>] [-OutputAssembly <string>] [-OutputType <OutputAssemblyType>] [-ReferencedAssemblies <string[]>] [-IgnoreWarnings] [-PassThru] [<CommonParameters>]

Add-Type [-TypeDefinition] <string> [-CodeDomProvider <CodeDomProvider>] [-CompilerParameters <CompilerParameters>] [-Language {<CSharp> | <CSharpVersion3> | <VisualBasic> | <JScript>}] [-OutputAssembly <string>] [-OutputType <OutputAssemblyType>] [-ReferencedAssemblies <string[]>] [-IgnoreWarnings] [-PassThru] [<CommonParameters>]

参考

http://yomon.hatenablog.com/entry/2013/06/05/PowerShellスクリプト内でC#コードを書いて使う

add-type

http://tech.guitarrapc.com/entry/2014/03/17/042253

add-type reference

https://technet.microsoft.com/en-us/library/dd315241.aspx

dll load

http://stackoverflow.com/questions/3079346/how-to-reference-net-assemblies-using-powershell

technet

https://blogs.technet.microsoft.com/stefan_gossner/2010/05/07/using-csharp-c-code-in-powershell-scripts/

WPFバインディング

WPF バインディング

まずは用語から、

  • バインディングソース 提供元オブジェクト
  • バインディングターゲット 提供先オブジェクト
  • ソースプロパティ 提供元プロパティ
  • ターゲットプロパティ 提供先プロパティ

バインディングソースになれるもの

  1. CLRオブジェクト
  2. 依存関係オブジェクト
  3. XMLオブジェクト
  4. 動的オブジェクト

XAMLのみでのBinding

box2のTextをbox1のTextにバインド。

<Window  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Binding1" 
    Height="100" 
    Width="100">

 <StackPanel>
     <TextBox Name="box1"
     Text="{Binding ElementName=box2, Path=Text, Mode=TwoWay}"/>
      <TextBox Name="box2"/>
 </StackPanel>
</Window>

スライダーの例

XAML

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Markup Extensions" Height="220" Width="175">

 <StackPanel>
     <TextBox Name="tbValue" Margin="10"
     Text="{Binding ElementName=sldrSlider, Path=Value, Mode=TwoWay}"/>
     <Slider Name="sldrSlider" TickPlacement="TopLeft" Margin="10"/>
  <Button Name="bnValue">Trigger</Button>
 </StackPanel>

</Window>

PS

if ($host.Version.Major -eq 3) {
    powershell.exe
} else {
    if ($host.Runspace.ApartmentState -eq "STA") {return}
    powershell.exe -version 2 -sta
}

if ($host.Version.Major -eq 3) {
 add-type -assembly WindowsBase,PresentationCore,PresentationFramework,System.Xml,System.xaml
} else {
 add-type -assembly WindowsBase,PresentationCore,PresentationFramework,System.Xml
}

$Xaml_win = @'
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Markup Extensions" Height="220" Width="175">

 <StackPanel>
     <TextBox Name="tbValue" Margin="10"
     Text="{Binding ElementName=sldrSlider, Path=Value, Mode=TwoWay}"/>
     <Slider Name="sldrSlider" TickPlacement="TopLeft" Margin="10"/>
  <Button Name="bnValue">Trigger</Button>
 </StackPanel>

</Window>
'@

$form = [System.Windows.Markup.XamlReader]::Parse($xaml_win)

$script = {
 $bindExpression = $form.FindName("tbValue").GetBindingExpression(`
      [System.Windows.Controls.TextBox]::TextProperty)
 $bindExpression.UpdateSource()
}
$form.findName("bnValue").add_Click($script)
[void]$Form.ShowDialog()
exit

C#を使った例

if ($host.Version.Major -eq 3) {
    powershell.exe
} else {
    if ($host.Runspace.ApartmentState -eq "STA") {return}
    powershell.exe -version 2 -sta
}


$xaml_win = @'
<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Markup Extensions" Height="220" Width="175">

 <StackPanel>
  <Label Name="displayText" Margin="5"/>
  <TextBox Name="sourceInfo">10</TextBox>
 </StackPanel>

</Window>
'@  # <--ブラウザによっては、コピペ時に行頭に空白出来る。空白削除する必要あり

$code = @'
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Data;

namespace MyBind
{
 public class BindingClass
 {
  public void bindData(object source, object dest)
  {
   TextBox s1 = (TextBox)source;
   Label   d1 = (Label)dest;

   //Bindingの生成
   Binding bindingShared = new Binding();

   // SourceとPathの設定
   bindingShared.Source = s1;

   bindingShared.Path = new PropertyPath( "Text" );

   //Bindingオブジェクトのセット
   d1.SetBinding( Label.ContentProperty, bindingShared );
   d1.SetBinding( Label.FontSizeProperty, bindingShared );
  }
 }
}
'@  # <--ブラウザによっては、コピペ時に行頭に空白出来る。空白削除する必要あり

if ($host.Version.Major -eq 3) {
 Add-Type $code -ReferencedAssemblies @("WindowsBase","PresentationCore","PresentationFramework","system.xaml")
} else {
 Add-Type $code -ReferencedAssemblies @("WindowsBase","PresentationCore","PresentationFramework")
}

$form = [System.Windows.Markup.XamlReader]::Parse($xaml_win)
$textBox = $form.FindName("sourceInfo")
$label = $form.FindName("displayText")
$mb = new-object MyBind.BindingClass
$mb.bindData($textBox, $label);
[void]$Form.ShowDialog()
exit

参考

C# binding

http://www.atmarkit.co.jp/ait/spv/1010/08/news123.html

PowerShell Binding Wxample

http://harebare01.blogspot.jp/2013/01/binding.html?m=1

Markup extension

http://harebare01.blogspot.jp/2013/01/blog-post_3.html?m=1

msdn バインディングソース

https://msdn.microsoft.com/ja-jp/library/ms743643(v=vs.110).aspx

CI on windows by PowerShell

CI

Windows環境のCI

Linuxならgit push -> post-update で何でも出来るが、windowsだとLinuxからのキック方法からして面倒。

例えば、

  1. Windows版OpenSSH
  2. 懐かしのWindows telnet server
  3. PowerShell Remote
  4. Jenkins
  5. Linux -> IIS -> webAPI

前提

現在考えている前提は、

  • git origin はlinux
  • CIターゲットがWin

何でも出来るが、どれもしっくりとこない。帯に短し襷に長しとはこの事か。

参考

DSCデプロイ

http://tech.guitarrapc.com/entry/2014/04/14/073657

お試し

http://tech.guitarrapc.com/entry/2014/12/14/062106

PowerShellのリスク

PowerShellのリスク

セキュリティ面ではPowerShellにはリスクがある。PowerShellではファイルアクセスなしにShellコードを実行される可能性がある。

きになる方は参考をご覧になって。

参考

http://colesec.inventedtheinternet.com/hacking-with-powershell-powersploit-and-invoke-shellcode/

ActiveDirectory by PowerShell

ActiveDirectory by PowerShell

基本コマンド

  1. New-ADUser
  2. Get-ADUser
  3. Set-ADUser
  4. Remove-ADUser
  5. Get-ADUserResultantPasswordPolicy

ユーザー作成

簡単に

New-ADUser taro -DisplayName 山田太郎

姓名指定

New-ADUser taro -Surname 山田 -GivenName 太郎 -DisplayName 山田太郎

OU指定

New-ADUser Naoto -Surname 山田 -GivenName 太郎 -Path "OU=Staff,DC=inc,DC=super,DC=com"

ユーザー取得

方法は3種類

  1. filter
  2. identity
  3. ldapfilter

全ユーザー

Get-ADUser -Filter *

メールで検索

Get-ADUser -Filter {mail -like "taro*"}

OUで検索

Get-ADUser -Filter * -SearchBase "OU=Staff,DC=inc,DC=super,DC=com"

Identity指定

Get-ADUser -Identity "S-1-5-21-4193795416-3281483866-4073542180-1110"

-Identityには下記を使用可能

  • 識別名
  • GUID
  • セキュリティ識別子
  • Samアカウント名

LDAP filter

Get-ADUser -LDAPFilter "(name=taro*)" -SearchScope Subtree -SearchBase "OU=Staff,DC=inc,DC=super,DC=com"

help

help Get-ADUser -Detailed

ユーザー削除

単純に

Remove-ADUser taro

Getして削除

Get-ADUser taro | Remove-ADUser

OU指定で削除

Remove-ADUser -Identity "CN=山田太郎,OU=staff,DC=inc,DC=super,DC=com"

ユーザー設定変更

-Identity指定

Set-ADUser -Identity taro -EmailAddress "taro@taro.com"

Get-ADUser経由

Get-ADUser -Identity taro | Set-ADUser -Department “Staff”

変数に受ける

$user = Get-ADUser "taro"
$user.EmailAddress = "taro@taro.com"

Set-ADUser -Instance $user

参考

http://blog.powershell-from.jp/?author=2