2013/10/31

[PowerShell] get-wmiobject invalid class - 模組多次Import 錯誤

最近在研究使用PowerShell 跟Hyper-V 互動
寫了一個 Script(.ps1)去建立&設定VM

Import-Module hyperv

$newvm = "JJ_VM1-3"
$vhdpath="C:\Users\Public\Documents\Hyper-V\Virtual hard disks\jj1-3.vhd"
$cpu=2
$memsize=1024
$memlimit=2048
$vmVirtualSwitch="Test2"


New-VM $newvm

Add-VMDisk -VM $newvm -Path $vhdpath 0 0

Set-VMCPUCount -VM $newvm -CPUCount $cpu 

Set-VMMemory -VM $newvm -Memory $memsize

Add-VMNic -VM $newvm -VirtualSwitch $vmVirtualSwitch

就可以成功的建立VM了

但是要再次執行時就發生了問題....
就會出現下面的錯誤訊息

Get-WmiObject : Invalid class

想說奇怪剛剛不是好好的嗎??
同樣的程式卻不能執行兩次...
重複試了很多次,還是出現相同的錯誤

最後關掉了PowerShell的視窗,重新開一個
執行Script,又成功建立VM了
但是當我要在執行第二次的時候又出現了相同的錯誤...

重複試了幾次只要是開視窗的第一次執行
都可以成功,後面就都會出現錯誤訊息了




仔細看了一下錯誤的訊息,好像是找不到模組
可是我的Script 的第一行不就 Import-Module
如果沒有Import 第一次也不會成功阿....

找很久之後終於找到了答案
原來是模組多次 Import造成這樣的問題....
以為頂多是 On 跟 Off 狀態而已

但是看看錯誤訊息跟上一篇沒有 Import模組的不一樣
一旦重複 Import之後就回不去了....只能重開視窗了

那有什麼方法可以避免重複 Import呢??

if(!(get-module hyperv))
{
   import-module hyperv
}
其實只要改成要Import前,先判斷模組是否已經存在了
如果沒有的話再Import,這樣就沒問題了


參考資料:
http://pshyperv.codeplex.com/discussions/230371

2013/10/30

[PowerShell]使用 PowerShell 來操控 Hyper-V

最近開始接觸到了Hyper-V,想著要如何去做到自動化的功能(建立VM等....)
找些網路上的文章有使用 PowerShell 和 C#
最後考量到 PowerShell 的彈性比較大,所以選用

我使用的是 Windows Server 2008 R2, 上面搭載Hyper-V 2.0 的版本
但是我手邊的參考書都是 Windows Server 2012 使用的都是 Hyper-V 3.0
書上沒有特別強調要去安裝設定 PowerShell ,我就以為 Windows Server 2008 R2也不用設定
但是在打第一句指令的時候就出錯了....

Get-VM 這個指令是取得機器上有那些VM


上網找了資料才發現原來還要替 PowerShell安裝 Hyper-V的套件才能使用

下載解壓縮之後,找到 install.cmd 用系統管理員的身分去執行


在安裝的過程會出現兩個錯誤,但是不會造成影響

接著會要確認登錄編輯程式,就按"是"



接著會跳出一個視窗就可以打 Get-VM 這個指令
就會跳出機器上的VM了

以為這樣就可以使用了,關掉視窗之後再打開就還是不行....
後來才發現使用之前 Import-Module ,但是還是出錯了...
奇怪剛剛登錄程式不是有按"是"...

後來知道要經過重開機之後才會重新登錄程式
也才找的到Hyper-V 的 Module


這時候Get-VM 這個指令就可找出VM了


這是我第一次接觸PowerShell & Hyper-V
所有的資訊都是Google來的,只是在這邊留個紀錄
我遇到了這個問題並且解決了這個問題

參考資料:

2013/10/6

[c#] 錄音程式

先前有寫到有使用WebCam錄影的功能
但是錄製的影片只有影像沒有聲音的
想要加入聲音,但是研究後發現 EmguCV無法加入聲音
而且只支援.avi格式的限制

所以就先來個寫個錄音的小程式
之後再來做整合

首先先拉畫面
有三個按鈕 "錄音"、"結束"、"播放"
接著是下面的 WindowsMediaPlayer的元件
這邊會遇到一些小問題,可能會在工具箱裡面找不到
在工具 -->選擇工具箱項目  可以設定

選擇 COM元件 ,將 Windows Media Player打勾

之後在工具箱裡就可以找到了



接著就可以開始寫程式碼了
這邊遇到一個新的東西 -- DllImport
稍微研究一下是說要使用第三方非在管理範圍中DLL的方法
還沒有完全研究完,等之後有比較清楚再進行補充

        //使用非託管(Unmanaged)的DLL
        [DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
        public static extern int mciSendString(
         string lpstrCommand,
         string lpstrReturnString,
         int uReturnLength,
         int hwndCallback
        );

mciSendString 是用來播放多媒體資料的API
參考文獻

開始錄音,有一些的參數設定
可以依據需求去調整
        //開始錄音
        private void button1_Click(object sender, EventArgs e)
        {
            mciSendString("set wave bitpersample 8", "", 0, 0);
            mciSendString("set wave samplespersec 20000", "", 0, 0);
            mciSendString("set wave channels 2", "", 0, 0);
            mciSendString("set wave format tag pcm", "", 0, 0);
            mciSendString("open new type WAVEAudio alias movie", "", 0, 0);
            mciSendString("record movie", "", 0, 0);

            button1.Enabled = false;
            button2.Enabled = true;
        }

結束錄音時,將檔案存在我們定義的路徑跟檔名
//結束錄音
        private void button2_Click(object sender, EventArgs e)
        {
            //檔案存放的路徑
            fileName = string.Format("{0}{1}{2}", voiceDirectory, DateTime.Now.ToString("yyyyMMddHmmss"), ".avi");

            mciSendString("stop movie", "", 0, 0);
            mciSendString("save movie " + fileName, "", 0, 0);  
            mciSendString("close movie", "", 0, 0);

            button1.Enabled = true;
            button2.Enabled = false;
            button3.Enabled = true;
        }



之後我們可以播放一下剛剛的錄音檔
看錄製的效果如何
//播放錄音檔
        private void button3_Click(object sender, EventArgs e)
        {
            if (!playing)
            {
                playing = true;
                button3.Text = "停止";
                //播放錄製的檔案
                this.axWindowsMediaPlayer1.URL = fileName;
                axWindowsMediaPlayer1.Ctlcontrols.play();
            }
            else
            {
                axWindowsMediaPlayer1.Ctlcontrols.stop();
                playing = false;
                button3.Text = "播放";
            }  
        }

這樣就可以達成簡單的錄音程式
如果要陽春一點,這邊就可以跟之前的WebCam錄影程式整合
雖然會是影像跟音效檔分開,但是只要在程式裡面使用兩個WindowsMediaPlayer的元件
就可以同時有影像跟聲音了....

但是這使用上還是很不方便
之後再來研究有沒有更完整的方法吧

DEMO