ラベル COM の投稿を表示しています。 すべての投稿を表示
ラベル COM の投稿を表示しています。 すべての投稿を表示

2015年4月7日火曜日

◆Wordのテンプレートを指定する

Wordの独自テンプレートを置いていたサーバーがリプレースされてパスが変わってしまったため、Word文書のテンプレートパスを一括で変更するスクリプトを作った。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019

$iPath = "\\hogeServer\public\*"
$ext = "docx"

$targetDocs = Get-ChildItem -Path $iPath -Include "*.$ext" -r 
$word = new-object -comObject "Word.Application" 
$word.Visible = $true

foreach($doc in $targetDocs
){ 
   
$word.Documents.Open($doc.fullname) | Out-Null
 
   
#Template設定
        $word.ActiveDocument.AttachedTemplate =
 
           
"\\hogehogeServer\pub\テンプレート.dotx"

    #保存して終了
    [void]$word.Application.ActiveDocument.
Save()
   
[void]$word.Application.ActiveDocument.
Close()
}


$word.Quit()
<!--EndFrag

ちなみに、ファイルサーバーの名前が変わってしまうと、Hostsファイルやlmhostsファイルでアドレスを置き換えてあげてもうまくいかない。(場合による?)

サーバー側のレジストリーでエイリアス名を設定すると良さそうではあるが・・・。

2013年11月27日水曜日

◆タスクスケジューラのジョブを纏めてエクスポートする

サーバーにしかけてあるジョブが増えてきたのでバックアップしておこうかと思ったのだが、GUIでは1つずつしかエクスポートできなさそう。

3.0が使えればコマンドレットが用意されているようだが、3.0を追加できないサーバーなので他の方法を探してみた。

「schtasks」か「Win32_ScheduledJob」あたりを使うのかなっと思って探しているとCOMを使ったそのものずはりのサンプルがあったので基本的にそのまま使わせていただいた。
Powershell, and exporting Windows Scheduled Tasks – TheGeekery

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015

$outPath = "f:\desktop\wk"
$outFileName = "{0}.xml"

$sch = New-Object -ComObject("Schedule.Service")
$sch.Connect("localhost")
$tasks = $sch.GetFolder("\").GetTasks(0
)
 

$outfile_temp = Join-Path $outPath $outFileName
 
$tasks | %{
$xml = $_.Xml
$task_name = $_.Name
$outfile = $outfile_temp -f 
$task_name
$xml
 | Out-File $outfile
}

image

2013年6月24日月曜日

◆別の資格情報で管理者として実行する2

タスクスケジューラに登録されたタスクの一覧を表示するスクリプトがあったので試してみた。

それ自体は特に問題はない。

複数サーバーのタスクをクライアントから覗けるとベターかと思うのだが、昇格した管理者権限が要求される。

以前PowerShell: ◆別の資格情報で管理者として実行するでちょっとやったのだが、もう一度ちゃんと調べてみたところPowerShellをネストして呼び出すというのが主流のようだ。(別の資格情報でPowerShellを起動し、その中でまたPowerShellを起動し昇格してコマンド実行)

コマンドを単独で実行するサンプルはあったのだが、スクリプトブロックを実行するサンプルが見当たらなかったため試行錯誤で作ってみた。

文字列の扱いが面倒で、都度エラーに対処しながら書いたのでスマートな書き方では無いかもしれない。(前回同様パスワードは予め保存しているものを使っている)

$password = ConvertTo-SecureString (gc f:\myPass)

$cred =

  New-Object System.Management.Automation.PsCredential "ad\adm",$password

 

 

$cmd = {

    $computers = 'hoge-sv','v064'  #★対象サーバー

    $service = New-Object -ComObject Schedule.Service

    $computers | %{

    $service.Connect($_)

    $folder = $service.GetFolder('\')

    $tasks = $folder.GetTasks(1)

    Write-Host 'ComputerName = ' $_ -ForegroundColor Yellow

    $tasks | ft Name, Enabled, LastRunTime, LastTaskResult, NextRunTime -auto

  }

}

 

$sc =

  "-command &{Start-Process PowerShell -ArgumentList {-noexit -command $cmd} -Verb runas }"

Start-Process -Credential $cred  -FilePath PowerShell.exe -ArgumentList $sc 

image

2013年2月6日水曜日

◆CABファイルを展開する

InfoPathのテンプレート(XSNファイル)をSharePoint2010からSharePoint2013に移行しようとしている。

残念なことにXSNファイル内にサーバーURLがハードコードされているので、そのままでは持って行けない。

テキストに変換して一括で修正できないか?

最近のパターンからするとZIP展開するとテキスト(xml)ファイルが出てくるパターンかと思ったのだがそうでもなさそう。

調べてみるとどうやらZIP形式ではなく、CABなんだそうな・・・。

PowerShellでのCABファイル操作を調べてみると以下にサンプルがあったので使わせてもらう。
Windows PowerShell で .CAB ファイルを作成する

展開処理を最小限に抜き出すとこんな感じ。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015

Function ConvertFrom-Cab()
{

Param
(
 
$cab ,
  $destination
)
 
$comObject = "Shell.Application"
  $shell = New-Object -Comobject $comObject
  if(!$?) { $(Throw "unable to create $comObject object"
)}
 
$sourceCab = $shell.Namespace($cab).
items()
 
$DestinationFolder = $shell.Namespace($destination
)
 
$DestinationFolder.CopyHere($sourceCab
)
}


ConvertFrom-Cab -cab "F:\Test.cab" -destination "F:\Desktop\wk"

ファイルの拡張子はXSNのままではうまくいかなかったのでCABにリネームした。

最初は気づかなかったが、ミニマムにしたソースを見てみるとZIPの解凍に似ている。

っていうか、もしかして同じ?

以前作ったZIP解凍のソースを見てみたら、同じですねぇ。

だから拡張子をCABにしないとダメなのね・・・。

2012年7月1日日曜日

◆スリープ時にiPod装着をチェックする

半年ほど前からiPodシャッフルを使っている。
安くてコンパクトで気に入っているのだが、USBに繋いで充電したままPCをスリープさせてしまうと逆に放電されてしまう。

朝気づくと充電がスッカラカンという事をなんどかやらかして、何かしら対策しないといけないと思い立った。(繋いでいるPCのUSBに依存した現象なのかもしれないが・・・)

スリープイベントを拾ってiPodがつながっていたら警告、って事にすれば良さそうだ。

Get-PSDriveでドライブ情報を取ってきてiPodかどうかを判定すれば良い。
幸い、DescriptionにiPodの名前が入っている。

っと思ったのだが、どうにもこうにもこいつが不思議な動作をする。
Descriptionに名前が入っている時と入っていない時があるのだ。
接続の都度違うとかではなくて、Get-PSDriveを呼ぶ都度?(環境)に違ったりする。
結局法則性がつかめなかったのでGet-PSDriveは諦めて「win32_usbhub」を使うことにした。

イベント自体は以前も使っているので以下と同様にしてみた。
PowerShell: ◆スリープ(Sleep)解除イベントを拾う

</
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032

#requires -version 2.0
#
# Sleep時にiPod接続の監視
#

$iPodString = "Apple Mobile Device USB Driver"
$identifier = "EnteringSuspend"
$query =
 
 
"Select * From Win32_PowerManagementEvent where EventType=4"
Register-WmiEvent -query $query -sourceidentifier $identifier 

try
{
 
While($true
){
   
$newEvent = Wait-Event -SourceIdentifier $identifier
    if(gwmi win32_usbhub | ?{$_.name -eq $iPodString
}){
     
$sam = New-Object -comObject SAPI.SpVoice
      $sam.Speak("i Pod is connecting."
 )
    }
       
   
Get-Event -SourceIdentifier $identifier | Remove-Event
     
  }
}

catch
{
   
Write-Warning "以下のエラーが発生しました"
    $error[0]
}
finally
{
   
#イベントを削除し購読をやめる
    Get-Event $identifier | Remove-Event
    Get-EventSubscriber -sourceidentifier $identifier |
 
     
Unregister-Event
}

警告は音声を使ってみたが、ココらへんは好みに応じて変更すれば良いだろう。

基本的にはUSBメモリーの抜き忘れなどにも使えそうなので用途はありそうだ。

2012年2月17日金曜日

◆Excel無しにExcelファイルを作る

サーバーでExcelファイルを作る必要があり、先日のPowerShell Advent Calendar 2011 : ATNDでPowerShell で Open XML ドキュメントを作成する - Hello Another World!が紹介されていましたので使わせて頂きました。

<PowerTools for Open XML>

  1. 環境
    • 以下から「Open XML SDK 2.0 for Microsoft Office」をインストール。とりあえず、「OpenXMLSDKv2.msi」だけインストールすれば良さそう。
    • 続いて、以下から「PowerTools for Open XML」をダウンロード。
      PowerTools for Open XML
    • 解凍するとC#のソリューションが出てくるのでVisualStudioでビルドする。
    • 「C:\Windows\System32\WindowsPowerShell\v1.0\Modules」に「OpenXmlPowerTools」フォルダーを作りビルドして出来上がった「OpenXmlPowerTools.dll」と「OpenXmlPowerTools.dll-Help.xml」を入れる。
      コマンドラインで「ipmo OpenXmlPowerTools」と打ってエラーにならなければ環境はOK
  2. 使い方
    • 以下のような感じで「Export-OpenXmlSpreadsheet」にオブジェクトをパイプしてやれば簡単にExcelファイルの出来上がり。
      ps | Export-OpenXmlSpreadsheet -OutputPath .\test.xlsx

実に簡単に使える。
非常に素晴らしい。

しかし、これ以降がよく判らない。
単純にこれまでCSVに出力していたものをExcelに変更するだけであればこれで問題ないのだが、せっかくExcelなので多少は書式を設定したり計算式を入れたりしたくなるのが人情というもの。
なんとなく以下のページを見ると、ほとんどがWord用に思えてしまう。
InfoQ: コマンドラインからOfficeドキュメントを生成する

完全に行き詰ってしまったので、ちょっと方向転換して以下のツールを試して見ることとした。
PowerShell で Excel 2007 のシートを操作する - Shigeya Tanabe's blog - Site Home - TechNet Blogs

なんとなくこちらはExcelのVBAライクに使えそうに見える。


<ExcelPackage.dll>

  1. 環境
  2. 使い方
    • dllをロードしておき、VBAと同様に「workbook」オブジェクトや「worksheets」オブジェクト「Cell」オブジェクトなどなんとなく見慣れたオブジェクトを使えば良さそう。
      田辺さんのサンプルをそのまま掲載しておきます。
      image

プロパティとかを見ると色々出来そうなので、あとでもう少し本格的に使ってみようと思います。

2011年11月8日火曜日

◆マイミュージック(MyMusic)の曲から詳細プロパティを取得する

娘に頼まれてWalkmanに曲を入れてやったのだが(ファイルコピーで入れれるのでWalkmanは簡単だ。iPodはソフトが重くて敵わん)、曲名が表示されないものがあるとのこと。

ん~、何でしょう。
私は音楽プレーヤーなんて使わないのでよく分からない・・・。

調べてみるとどうやら単純にファイル名を表示しているわけではなく詳細プロパティにある情報から表示しているようだ。
image

曲名が表示されないファイルを見ると、このタイトルが入っていない。
image

エクスプローラーで入力もできるのだがタイトルだけであればファイル名からコピーできれば簡単だ。

そこで、ココらへんの情報を取ってこれるのか調べてみたのだが、どうやらShell.Applicationで可能なようだ。

プロパティの値自体は取れたのだがプロパティ名称の取り方が判らずちょっと苦労した。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022

#$path = "D:\Music\Hey!Say!JUMP"
$path = "D:\Music"
$MusicItems = @()

$shell = New-Object -Com Shell.Application
dir $path -r | ?{-not $_.PsIsContainer} | %
{
 
$filename = $_.
name
 
$dirname = $_.
DirectoryName
 
$folderobj = $shell.NameSpace($dirname
)
 
$item = $folderobj.ParseName($filename
) 
 
$MusicItem = New-Object PsObject |
 
   
Add-Member NoteProperty ファイル名 $_.name -pass
  0..40 | %
{
   
$MusicItem |
 
   
Add-Member NoteProperty
 `
     
-Name $folderobj.GetDetailsOf($folderobj.Items(),$_
) `
     
-Value $folderobj.GetDetailsOf($item,$_
)
  } 
 
$MusicItems += $MusicItem
}

$MusicItems | ft ファイル名,アルバム,タイトル
<!-
image

あとは更新の仕方となるのだが、時間が無いので後で調べてみる。

プロパティ名称とかは違うだろうがMusicファイル以外にも使えそうだ・・・。

2011年6月21日火曜日

◆Zipファイル(圧縮ファイル)を作る2

PowerShell: ◆Zipファイル(圧縮ファイル)を作る(改)で作ったサンプルを基に実際にファルのバックアップ処理を行ってみたのだが、なんとなく動きが怪しい。
ファイルに排他がかかっていたり、出来上がったZipファイルがヘッダーのみだったりと動作が安定しない。

色々と試行錯誤し状況から考えるに、どうもこのCopyHereメソッドは非同期で動いているんじゃないかしらん?と思い始めた。

ネットを調べると案の定、同じ現象に遭遇している人がちらほら居て、やはり非同期動作のようだ。(圧縮は非同期、解凍は同期とのことらしい)

そこで、圧縮後に行っていた処理を止めてCopyHereが最終処理になるよう修正してみた。
ISE環境でテストしてOKだったのでタスクスケジューラに登録して運用したところ、やはりうまくいかない。

ん~、そうかCopyHereが終わる前にプロセスが終わってしまうのねん・・・。

また、ネットで調べてみると以下のスクリプトが公開されていた。
ZIP.PS1の詳細情報 : Vector ソフトを探す!

汎用的に使うのであればこれを使わせていただくのが良さそうだ。

私的には、そこまでではない(スケジューラタスクなので時間が掛かっても問題ない)ので単純にCopyHereの後にSleepを噛ませて回避した。

2011年4月26日火曜日

◆CSVファイルをExcelで開く2

PowerShell: ◆CSVファイルをExcelで開くを少しだけ変更してみた。
CSVファイルは文字列項目をダブルコーテーションで囲んでいるケースが多々ある。
そんな場合はその項目だけに文字列属性を指定してあげることで、前回不満だった数値項目が左寄せされてしまう(計算とかも出来なくなる)のを回避できそうだ。

私のあやふやな正規表現での判定文を追加した。
$_ -match '".*"'

001
002
003
004
005
006
007
008
009
010
011

$path = $args[0]
$item = (Get-Content $path -TotalCount 1) -split ','
$item | %{$atts = @()}{if($_ -match '".*"'){$atts += 2}else{$atts += 1}}
$excel = New-Object -Com Excel.Application
$excelBook = $excel.Workbooks.Add()
$excel.Visible = 
$true
$query
 = $excel.ActiveSheet.QueryTables.Add(
"TEXT;$path",$excel.Application.Range('$A$1'))
$query.TextFileCommaDelimiter = 
$true
$query
.TextFileColumnDataTypes = 
$atts
$query
.Refresh($false) | Out-Null

2011年4月25日月曜日

◆CSVファイルをExcelで開く

拡張子CSVはデフォルトではExcelに関連付けられている。(当然Excelが入っていればだが)
カラム毎に表示されるのでメモ帳で開くよりは見やすい。
ただし、CSVファイルをダブルクリックして開いた場合はデータの内容に応じてExcelが自動的にフォーマットしてくれるのだが、これが大きなお世話になることもある。

例えば、以下のようなCSVファイルを開くと、こんな感じになってしまう。

"00001","1-1",1,-66
"00003","2-1",3,4


image

これを回避するにはテキストとしてインポートして、その時に表示されるウィザードにてカラムの属性をそれぞれ指定してあげれば良い。
毎回同じフォーマットのCSVを開くのであればこれをマクロ登録しておけば良いのだが、フォーマットの違うCSVを開く場合はその都度カラム属性の指定が必要になる。

そこで、とりあえずフォーマット変更されないようにすべての項目に対して文字列属性を指定してExcelで開くスクリプトを作ってみた。

001
002
003
004
005
006
007
008
009
010
011
012

$path = $args[0]
$itemCount = ((Get-Content $path -TotalCount 1) -split ",").Count
$excel = New-Object -Com Excel.Application
$excelBook = $excel.Workbooks.Add()
$excel.Visible = 
$true
$query
 = $excel.ActiveSheet.QueryTables.Add(
"TEXT;$path",$excel.Application.Range('$A$1'))
$query.TextFileCommaDelimiter = 
$true
$arr
 = [char[]]("2" * $itemCount) | %{[int]::Parse($_)}

$query.TextFileColumnDataTypes = 
$arr
$query
.Refresh($false) | Out-Null

結果はこんな感じになる。
image

純粋な数値項目も左寄せになってしまい今一歩感もあるが、とりあえずさっきよりはましではなかろうか。

ちなみに、属性の指定はカラムの数分だけ配列で指定すれば良さそうだ。
ここでは「文字列属性」ということで2を指定している。

またCSVの拡張子に関連付けるには、このスクリプトを呼び出すバッチファイルを作る必要がありそうだ。(ps1ファイルは実行形式として扱われていないため)

2011年4月15日金曜日

◆自動で閉じるメッセージボックス

これまで、メッセージボックスを表示するには当たり前のように.NETのMessageBoxクラスを使ってきた。
しかし、こいつは事前にアセンブリーのロードが必要だったりして必ずしもPowershellから使いやすいとは言えない。

MessageBoxクラスの代わりにWSHを使うともう少し簡単に表示する事が可能だ。(WSHユーザーには当たり前すぎることでしょうが私は使っていなかったので)

しかも、定義をみるとこいつは指定時間後に自動で閉じるなんて機能もあるらしい。

こんな感じだ。

001
002
003
004
005

$message = "C:\の中身を表示しました。"
dir c:\
      
(
New-Object -ComObject wscript.shell).
popup(
   
$message,1,"TestTitle") | 
out-null
Write-Host
 $message -fore Yellow
<!--EndFragment--

自動で閉じる機能が使えるかどうかは別として、1行でメッセージボックスを表示できるのは嬉しい。

今後はこいつを使おう。

2011年3月17日木曜日

◆Zipファイル(圧縮ファイル)を作る(改)

ちょっと修正と補足。
17行目はIO.PathクラスのChangeExtensionメソッドを使ったほうがスマートっぽい。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022

<#
.SYNOPSIS
  Zip圧縮ファイルを作る
.DESCRIPTION
  フォルダーまたはファイルを指定して同一フォルダーにZipファイルを作る
.EXAMPLE
  makezip.ps1 "D:\test"
  makezip.ps1 "D:\test\sample.txt"
#>

param
(
 
[parameter(Mandatory=$true,
    HelpMessage="圧縮したいファイル(フォルダ)のパスを指定してください。")]
   [ValidateScript({Test-Path $_})]
  $target
 
)

$targetobj = Get-Item  $target
#$zipfile = ($targetobj.fullname -replace $targetobj.Extension,"") + ".zip"
$zipfile = [IO.Path]::ChangeExtension($targetobj.fullname, ".zip")
Set-Content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
$zip = (new-object -com shell.application).NameSpace($zipfile) 

$zip.CopyHere(
$target)

18行目の("$([char]0)" * 18))は雰囲気で判るとは思うが、Asciiコードがゼロのキャラクター(文字)を18個つなげるって事。

PS>("$([char]0)" * 18) -eq (([char]0).ToString() * 18)
True