2011年07月28日

Formを突き抜けてFormの後ろ側をクリックできるようにする

レイヤードウィンドウを使用してウィンドウの後ろにあるオブジェクトを操作出来るようにする。
レイヤードウィンドウを使用するのでウィンドウとして表示する画像ファイルを別途用意する。

WIN32APIを使うのでAPI宣言。
    [DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteObject(IntPtr hobject);

[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int DeleteDC(IntPtr hdc);

[DllImport("user32")]
public static extern IntPtr GetDC(IntPtr hWnd);

[DllImport("user32")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

public const int AC_SRC_OVER = 0;
public const int AC_SRC_ALPHA = 1;
public const int ULW_ALPHA = 2;


[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct BLENDFUNCTION
{
public byte BlendOp;
public byte BlendFlags;
public byte SourceConstantAlpha;
public byte AlphaFormat;
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int UpdateLayeredWindow(
IntPtr hwnd,
IntPtr hdcDst,
[System.Runtime.InteropServices.In()]
ref Point pptDst,
[System.Runtime.InteropServices.In()]
ref Size psize,
IntPtr hdcSrc,
[System.Runtime.InteropServices.In()]
ref Point pptSrc,
int crKey,
[System.Runtime.InteropServices.In()]
ref BLENDFUNCTION pblend,
int dwFlags
);

フォームの CreateParams プロパティを override してレイヤードウィンドウにする。
フォームを突き抜けるには下記のWS_EX_TRANSPARENTをスタイルに設定するのがポイント。
    protected override CreateParams CreateParams
{
get
{
const int WS_EX_LAYERED = 0x00080000;
const int WS_EX_TRANSPARENT = 0x00000020;
const int WS_BORDER = 0x00800000;
const int WS_THICKFRAME = 0x00040000;

System.Windows.Forms.CreateParams cp = base.CreateParams;

cp.ExStyle = cp.ExStyle | WS_EX_LAYERED;
cp.ExStyle = cp.ExStyle | WS_EX_TRANSPARENT;
if (this.FormBorderStyle != FormBorderStyle.None) {
cp.Style = cp.Style & (~WS_BORDER);
cp.Style = cp.Style & (~WS_THICKFRAME);
}

return cp;
}
}

レイヤードウィンドウを設定するメソッドを定義。
BLENDFUNCTION構造体のSourceConstantAlphaの値で透明度を指定できるのでお好みで設定する。
    private void SetLayeredWindow(Bitmap bmp)
{
IntPtr screenDc = IntPtr.Zero;
IntPtr memDc = IntPtr.Zero;
IntPtr hbmp = IntPtr.Zero;
IntPtr oldbmp = IntPtr.Zero;

try {

screenDc = GetDC(IntPtr.Zero);
memDc = CreateCompatibleDC(screenDc);
hbmp = bmp.GetHbitmap(Color.FromArgb(0));
oldbmp = SelectObject(memDc, hbmp);

// イメージの透過情報を設定
BLENDFUNCTION bf = new BLENDFUNCTION();
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 128; // 50%の透過度でイメージを表示する!
bf.AlphaFormat = AC_SRC_ALPHA;

// ウィンドウ更新
this.Size = new Size(bmp.Width, bmp.Height);
Point pptDst = new Point(this.Left, this.Top);
Size psize = new Size(this.Width, this.Height);
Point pptSrc = new Point(0, 0);
User32.UpdateLayeredWindow(this.Handle, screenDc, ref pptDst, ref psize, memDc, ref pptSrc, 0, ref bf, ULW_ALPHA);

} finally {
if (screenDc != IntPtr.Zero) {
ReleaseDC(IntPtr.Zero, screenDc);
}
if (hbmp != IntPtr.Zero) {
SelectObject(memDc, oldbmp);
DeleteObject(hbmp);
}
if (memDc != IntPtr.Zero) {
DeleteDC(memDc);
}
}
}

あとはフォームのコンストラクタあたりでイメージファイルを読み込んで上記のメソッドを呼んであげる。
    public Form1()
{
Bitmap bmp = new Bitmap(@"C:\test.png");

Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bd = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

Bitmap ret = new Bitmap(bd.Width, bd.Height, bd.Stride, PixelFormat.Format32bppArgb, bd.Scan0);

bmp.UnlockBits(bd);

SetLayeredWindow(bmp);
}


申し訳ないがここにのせたソース、動いてるソースを切って貼ったものではあるけれども、貼った後の検証をしてないのでコピペして動かなかった場合、各自アドリブでの対応をお願いしたい。
posted by なまい at 20:45| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2011年06月25日

フォームをアクティブにせずに開く

フォームを非アクティブで開いて、呼び出しもとのウィンドウにフォーカスを残したままにするには Form の ShowWithoutActivation プロパティを override して true を返すようにすれば良い。
    protected override bool ShowWithoutActivation
{
get
{
return true;
}
}
posted by なまい at 12:54| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年10月30日

ウィンドウを表示させないようにする(タスクバー、Alt+Tabにも)

ウィンドウを全く表示させないようにする。
ShowInTaskBarプロパティをfalseにしてもAlt+Tabには表示されてしまうがフォームのCreateParamsプロパティをoverrideし、ウィンドウが表示されなくする。
    protected override CreateParams CreateParams
{
get {
const int WS_EX_TOOLWINDOW = 0x80;
const long WS_POPUP = 0x80000000L;
const int WS_VISIBLE = 0x10000000;
const int WS_SYSMENU = 0x80000;
const int WS_MAXIMIZEBOX = 0x10000;

CreateParams cp = base.CreateParams;
cp.ExStyle = WS_EX_TOOLWINDOW;
cp.Style = unchecked((int) WS_POPUP) | WS_VISIBLE | WS_SYSMENU | WS_MAXIMIZEBOX;
cp.Width = 0;
cp.Height = 0;

return cp;
}
}
posted by なまい at 19:07| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年02月20日

時間のかかる処理を別スレッドで処理する

時間のかかる処理を別スレッドで処理するには、System.Threading.Threadクラスを使用する。
別スレッド内からラベルなどのコントロールを操作するにはInvoke()メソッドを使用しないと例外が発生するので注意。
    // スレッドクラス
private System.Threading.Thread thread_ = null;

public Form1()
{
InitializeComponent();
this.button1.Click += new EventHandler(button1_Click);
}


private void button1_Click(object sender, EventArgs e)
{
//スレッドを作成&開始
thread_ = new System.Threading.Thread(new System.Threading.ThreadStart(Execute));
thread_.IsBackground = true;
this.thread_.SetApartmentState(System.Threading.ApartmentState.STA);
thread_.Start();
}


private void Execute()
{
// 時間のかかる処理をここで行う

// ラベルに進捗状況などを表示
this.Invoke(new MethodInvoker(Label1Update));
}


private void Label1Update()
{
this.label1.Text = "時間のかかる処理中";
}
posted by なまい at 22:24| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2010年01月11日

オブジェクトの型を判定する

オブジェクトの型を判定するにはis演算子を使用する
    if (obj is TextBox) {
// テキストボックスです;
} else if (obj is Label) {
// ラベルです
} else if (obj is ComboBox) {
// コンボボックスです
} else if (obj is ListBox) {
// リストボックスです
}


posted by なまい at 08:16| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2009年11月21日

Windowsキー押下を無効にする

キーボードフックを使ってWindowsキーを無効にする。
Form1のコンストラクタでキーボードフックを開始する。
Form1に配置されたbutton1が押されたらキーボードフックを解除する。
KeyHookProc()で対象のキーか判断し対象のキーなら1を返す。

public partial class Form1 : Form
{

private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

[DllImport("user32.dll", CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
private static extern bool UnhookWindowsHookEx(int idHook);

[DllImport("user32.dll",CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

private const int WH_KEYBOARD_LL = 0x0D;

private struct KeyBoardLLHookStruct {
public int vkCode;
public int scanCode;
public int flags;
public int time;
public IntPtr dwExtraInfo;
}

private static int hHook = 0;

// コンストラクタ
public Form1()
{
InitializeComponent();

// イベント登録
this.button1.Click += new EventHandler(button1_Click);

// キーフック開始
IntPtr handle = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, new HookProc(Form1.KeyHookProc), handle, 0);
if(hHook == 0){
// キーフック失敗;
return;
}
}

// ボタンクリック
// キーボードフックを解除
private void button1_Click(object sender, EventArgs e)
{
if (hHook != 0) {
bool ret = UnhookWindowsHookEx(hHook);
if (ret == false ) {
// キーフック解除失敗;
return;
}
hHook = 0;
}
}

// KeyHookプロシージャ
private static int KeyHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
if (Form1.ActiveForm != null) {
KeyBoardLLHookStruct MyHookStruct = (KeyBoardLLHookStruct) Marshal.PtrToStructure(lParam, typeof(KeyBoardLLHookStruct));
if (nCode == 0) {
// 91 : 左Windowsキー 92 : 右Windowsキー
if ((MyHookStruct.vkCode == 91) || (MyHookStruct.vkCode == 92)) {
// 0以外を返すと無効
return 1;
}
}
}
// 対象のキー以外
return CallNextHookEx(hHook, nCode, wParam, lParam);
}

}

VisualStudioからF05デバッグ開始で実行する場合は、プロジェクト−プロパティ−デバッグ−VisualStudioホスティングプロセスを有効にする のチェックを外しておかないと正しく動作しないので注意。
exeで動かす場合は普通に動く。
タグ:Win32API
posted by なまい at 15:00| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2009年07月16日

ラベルの背景色を透過にする

ラベルの BackColor プロパティを Color.Transparent に設定すれば背景色が親コンテナの背景色になるようになる。
コンテナがPanelとかだとデザイナで配置しただけで勝手に親コンテナを設定してくれるけど、別のラベルとかPictureBoxの上にラベルを置いて背景を透過にしたいときは、ソース上で設定する。
    this.Label1.BackColor = Color.Transparent;
this.Label1.Parent = this.PictureBox1;
this.Label1.Location -= (Size)this.PictureBox1.Location;
まず、透過にしたいラベルの背景色をColor.Transparentに設定
ラベルの親にPictureBoxを設定。
Locationは親コンテナの左上からの座標なので新しい親コンテナ(PictureBox)にあわせて再設定。
# 実際はLocationの設定は負値にならないように考慮する必要有り。
posted by なまい at 01:25| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2009年02月10日

日付および時刻の値のミリ秒部分を表示する

DateTimeオブジェクトを文字列変換する際にミリ秒部分まで含めて取得。
ToString()の書式指定文字列に「f」を指定してやるとミリ秒を取得できる。
最大7桁まで指定可能。8桁以上指定すると例外が発生。
「f」の代わりに「F」を指定すると、ミリ秒値に後続のゼロがあれる場合後続の0を除外して出力される。
    // 9999/12/31 23:59:59.990
   MessageBox.Show(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.fff"));

   // 9999/12/31 23:59:59.99
   MessageBox.Show(System.DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss.FFF"));
posted by なまい at 15:22| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年11月15日

クリップボードからのデータ取得

クリップボードからデータを取得。取得前にGetDataPresent()メソッドで取得しようとしているデータ形式をサポートしているかチェックしてからチェックする。
サンプルは文字列データの取得。
    string str = "";
    if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Text) == true) {
        str = Clipboard.GetDataObject().GetData(System.Windows.Forms.DataFormats.Text).ToString();
    }
posted by なまい at 21:34| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月31日

CrystalReportsで動的イメージ印刷

VisualStudio付属のCrystalReportsで印刷時に任意のイメージファイルを印刷する方法。

1. プロジェクトの新規作成でCrystalReportアプリケーションを作成
2. プロジェクトにデータセットを追加
  (プロジェクト - 新しい項目の追加 - データ - データセット)
3. データセットにDataTableを追加
  (2で作成したデータセットを開いて、右クリック - 追加 - DataTable)
4. DataTableにイメージ格納用のカラムを追加
  (3のDataTableで、右クリック - 追加 - 列)
5. 追加した列のDataTypeプロパティを、System.Byte[]に変更
6. フィールドエクスプローラを開いてデータベースフィールドで右クリック
  データベースエキスパートを開く
7. プロジェクトデータ - ADO.NETデータセットを展開し、3で追加したDataTableを選択したテーブルに追加
8. データベースフィールドに追加したDataTableが表示されるので、4で追加したカラムをレポートに貼り付け
9. 以下のコードを実装。パラメータには印刷するイメージファイルパスを指定
    private void PrintReport(string fn)
    {
 
        // レポートのインスタンス生成
        CrystalReport1 cr = new CrystalReport1();
 
        // イメージファイル読み込み
        FileStream fs = new FileStream(fn, FileMode.Open);
        BinaryReader br = new BinaryReader(fs);
 
        // データセット生成・イメージのセット
        DataSet1 data = new DataSet1();
        DataRow  dr = data.Tables[0].NewRow();
        dr["DataColumn1"] = br.ReadBytes((int)br.BaseStream.Length);
        data.Tables[0].Rows.Add(dr);
 
        cr.SetDataSource(data);
 
 
        Image img = Image.FromStream(fs);
 
        // イメージサイズをPixcelからTwipに変換 (1インチ = 1440TWIPS)
        float imgw = (img.Width / img.HorizontalResolution) * 1440;
        float imgh = (img.Height / img.VerticalResolution) * 1440;
 
        // 幅と高さの各拡大縮小率を算出
        float perx = cr.ReportDefinition.ReportObjects["DataColumn11"].Width / imgw;
        float pery = cr.ReportDefinition.ReportObjects["DataColumn11"].Height / imgh;
 
        // 拡大縮小率の大きい方にあわせてBLOBフィールドのサイズを調整
        if (perx > pery) {
            cr.ReportDefinition.ReportObjects["DataColumn11"].Width = (int)(imgw * pery);
            cr.ReportDefinition.ReportObjects["DataColumn11"].Height = (int)(imgh * pery);
        }else{
            cr.ReportDefinition.ReportObjects["DataColumn11"].Width = (int)(imgw * perx);
            cr.ReportDefinition.ReportObjects["DataColumn11"].Height = (int)(imgh * perx);
        }
 
        br.Close();
        fs.Close();
 
        this.crystalReportViewer1.ReportSource = cr;
    }
どうも出力されるイメージは、8でレポートに貼り付けたBLOBフィールドのサイズに合わせてリサイズされる模様。
なので上記のソースではイメージサイズにあわせてBLOBフィールドのサイズを変更してる。
ちなみにCrystalReportのサイズの単位はTwipなので、イメージサイズをTwip単位に変換して処理してる。

我ながらよく分からん説明になったのでサンプルプロジェクトを添付する。添付のプロジェクトはVisualStudio2008で作成してるけど2005でも同じソースで動くはず。

サンプルプロジェクト
posted by なまい at 17:29| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月24日

Substringのバイト指定版(for C#)

文字列をバイト数で切り出す。バイト数はShift-JISエンコーディングでのバイト数(半角1byte、全角2byte)
まず、切り出し開始位置を決定し、開始位置から1文字ずつ指定バイト数を超えるまで残りの文字列を取得する。
以前に書いたVB.NetのコードをC#に書き換えただけ。
    public string ByteSubstring(string value, int startindex, int length)
    {
        string ret = "";          // 切り出した文字列
        int start = 0;
        Encoding sjis = Encoding.GetEncoding("Shift-JIS");
 
        if (startindex < 0)  { startindex = 0;  }
        if (length < 0) { length = 0; }
 
        // 開始位置を取得
        if (startindex == 0) {
            // 先頭を指定された
            start = 0;
        }else{
            // 先頭以外を指定された
            int bytecnt = 0;
            for (int i=0; i<value.Length; i++)
            {
                // 先頭からのバイト数を取得
                bytecnt += sjis.GetByteCount(value.Substring(i, 1));
                if (bytecnt >= startindex) {
                    // 先頭からのバイト数が開始位置以上になる文字の次の文字が開始位置
                    start = i + 1;
                    break;
                }
            }
        }
        
        // 指定された開始位置が文字の途中だった場合、切出しサイズをマイナス1!
        if (length > 0) {
            if (sjis.GetByteCount(value.Substring(0, start)) > startindex) {
                length--;
            }
        }

        // 決定した開始位置から1文字ずつ取得し、指定バイト数を超えるまで取得
        for (int i=0; i<value.Length; i++)
        {
            if (i >= start) {
                if ((sjis.GetByteCount(ret + value.Substring(i, 1)) <= length) || (length == 0)) {  
                    ret += value.Substring(i, 1);
                }
            }
        }
        return ret;
    }
2009/03/24 修正
ソースコードの不等号(<、>)がタグとごっちゃになっておかしなコードになっていました。
ご指摘ありがとうございました。
posted by なまい at 00:30| Comment(5) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月22日

[WMI] スキャナの電源チェック

お仕事でUSB接続のスキャナの電源ON・OFFチェックを行う必要に迫られた時に取った方法。
言われたときは、「電源入れりゃ、コントロールパネルの「スキャナとカメラ」にスキャナ出てくるんだから、なんしか取れるやろ」と思って余裕ぶっこいてた訳ですが、イロイロ調べても出てこない。
某外資系メーカーの人間も電源の状態取る方法は無いとか言いやがるし。
試行錯誤した結果、以下の方法で解決させた。

 1. Win32_USBControllerDeviceでUSBデバイスを取得
 2. DependentプロパティからデバイスIDを取得
 3. 2のデバイスIDを使いWin32_PnPEntityからデバイスの情報取得
 4. Nameプロパティの値が対象スキャナのNameプロパティと一致するかチェック
 5. 一致すれば電源ON、一致するものが無ければ電源OFF
    private bool IsScannerPowerON(string value)
    {
        string query = "Select * From Win32_USBControllerDevice";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
        foreach (ManagementObject mo in moc)
        {
            // デバイスIDを抜き出し
            string device = mo.Properties["Dependent"].Value.ToString();
            device = device.Replace(('"').ToString(), "");
            device = device.Split('=')[1];
 
            // デバイスIDからUSBデバイスに関する情報を取得
            query = "Select * From Win32_PnPEntity Where DeviceID = '" + device + "'";
            ManagementObjectSearcher usbmos = new ManagementObjectSearcher(query);
            ManagementObjectCollection usbmoc = usbmos.Get();
            foreach (ManagementObject usbmo in usbmoc)
            {
                // Nameプロパティの値が指定されたものと同じなら電源ONと判断
                if (usbmo.Properties["Name"].Value.ToString() == value) {
                    return true;
                }
            }
        }
 
        return false;
    }
サンプルではパラメータにNameプロパティの値を指定している。電源ONならtrueを電源OFFまたはケーブルが接続されてない場合はfalseを返す。
こいつの問題点はあらかじめスキャナが接続されたときののNameプロパティの値が分かってないとつかえないところ。
posted by なまい at 21:30| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月21日

[WMI] デフォルトゲートウェイを設定(複数対応版)

前回のデフォルトゲートウェイ設定を複数指定に対応させて、なおかつ自動メトリックにも対応させる。
まず、複数指定出来るメソッドを作成。第三引数のメトリックは自動にしたいやつは「0」を指定する。
    public void SetDefaultGateway(string adapter, List<string> gateway, List<int> metric) 
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE"; 
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query); 
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
 
                string[] gateways = new string[gateway.Count]; 
                for (int i=0; i<gateway.Count; i++) {
                    gateways[i] = gateway[i];   
                }
 
                Int16[] metrics = new Int16[metric.Count];
                for (int i=0; i<metric.Count;  i++) {
                    if ((metric[i] > 0) && (metric[i] < 10000)) { 
                        metrics[i] = (Int16)metric[i];
                    }else{
                        // 自動指定された場合は一旦デフォルト値の1で設定する。
                        // 設定後レジストリをいじって自動にする
                        metrics[i] = (Int16)1;
                    }
                }
  
                object[] args = new object[] { gateways, metrics };
 
                // メソッド実行
                uint res = (uint)mo.InvokeMethod("SetGateways", args);
                switch (res){
                case 0:
                    // 成功
                    this.SetAutoMetric(adapter, metric);    // このメソッドで自動メトリックに設定 詳細は後述
                    break;
                case 1:
                    // 成功(再起動後に有効)
                    this.SetAutoMetric(adapter, metric);    // このメソッドで自動メトリックに設定 詳細は後述
                    break;
                default:
                    // 失敗
                    break;
                }
            }
        }
    }
んで、前回のゲートウェイ単独設定メソッドは以下の様に変更しちゃう。
    public void SetDefaultGateway(string adapter, string gateway, int metric) 
    {
        List<string> gateways = new List<string>();
        List<int> metrics = new List<int>();
 
        // 上で作成したメソッドをコールしちゃう
        gateways.Add(gateway);
        metrics.Add(metric);
        this.SetDefaultGateway(adapter, gateways, metrics);
    }
あとは、こっそり追加したSetAutoMetric()メソッドの実装。メトリックの値は以下のレジストリキーが複数行文字列値で持ってる。ちなみにレジストリの値が「0」のやつが自動になる。
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{NICのSettingID}\DefaultGatewayMetric   
メトリックのレジストリ設定を変更するメソッド
    public bool SetAutoMetric(string adapter, List<int> metric)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                string key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
                key += mo.Properties["SettingID"].Value.ToString();
 
                Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(key, true);
                string[] metrics = new string[metric.Count];
                for (int i=0; i<metric.Count; i++) {
                    if ((metric[i] > 0) && (metric[i] < 10000)) {
                        metrics[i] = metric[i].ToString();   
                    }else{
                        metrics[i] = "0";
                    }
                }
                regkey.SetValue("DefaultGatewayMetric", metrics);
                regkey.Close();
                return true;
            }
        }
        return false;
    }
posted by なまい at 00:10| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月18日

[WMI] デフォルトゲートウェイを設定

指定したネットワークアダプタのデフォルトゲートウェイとメトリックを設定する。
第二引数にゲートウェイ、第三引数にメトリックを指定。メトリックの範囲は1〜9999なので、範囲外を指定された場合はデフォルト値の1で作成。
    public void SetDefaultGateway(string adapter, string gateway, int metric) 
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE"; 
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query); 
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
 
                // SetGatewaysメソッドへ渡すパラメータ生成
                object[] args = null;
                if ((metric > 0) && (metric < 10000)) {
                    args = new object[] { new string[] { gateway }, new Int16[] { (Int16)metric } }; 
                }else{
                    // 範囲外のメトリックの場合は、Nullを指定
                    // Nullを指定するとデフォルトの「1」で設定される
                    args = new object[] { new string[] { gateway }, null };
                }
 
                // メソッド実行
                uint res = (uint)mo.InvokeMethod("SetGateways", args);
                switch (res){
                case 0:
                    // 成功
                    break;
                case 1:
                    // 成功(再起動後に有効)
                    break;
                default:
                    // 失敗
                    break;
                }
            }
        }
    }
SetGatewaysメソッドへ渡すメトリックにnullを指定したら自動メトリックになるかと期待したけど、デフォルト値の1で設定された。
自動メトリックに設定するにはレジストリいじらないとダメかも。
posted by なまい at 11:20| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月17日

[WMI] ゲートウェイメトリックの一覧を取得

指定したネットワークアダプタに割り当てられているゲートウェイメトリックの一覧を取得する。
取得されるメトリックの一覧は、DefaultIPGatewayプロパティで取得した値と対になる。
自動メトリックに設定されている場合はOSが割り当てた値が取得される。
    public List<int> GetDefaultGatewayMetrics(string adapter)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE"; 
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        List<int> ret = new List<int>();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                Int16[] metrics = (Int16[])mo["GatewayCostMetric"];
                foreach (Int16 metric in metrics) {
                    ret.Add((int)metric);
                }
            }
        }
 
        return ret;
    }
posted by なまい at 11:00| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月12日

[WMI] デフォルトゲートウェイの一覧を取得

指定したネットワークアダプタに割り当てられているデフォルトゲートウェイの一覧を取得する。
    public List<string> GetDefaultGateways(string adapter)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        List<string> ret = new List<string>();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                string[] gateways = (string[])mo["DefaultIPGateway"];
                foreach (string gateway in gateways) {
                    ret.Add(gateway);
                }
            }
        }
 
        return ret;
    }
posted by なまい at 20:53| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月11日

[WMI] DNSサーバアドレスの取得方法を取得

指定したネットワークアダプタのDNSサーバアドレスの取得方法を取得する。どうもWMIから取得するのは無理っぽいので対象のNICのレジストリの値を参照する。参照するキーは以下
  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\{NICのSettingID}\NameServer  
DNSサーバアドレスに指定がある場合は指定されたアドレスが入ってるので、この値が空なら自動取得と判断。
以下のサンプルでは自動取得の場合はtrue、そうでない場合はfalseを返す。
    public bool IsDNSAuto(string adapter)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                string key = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
                key += mo.Properties["SettingID"].Value.ToString();
 
                Microsoft.Win32.RegistryKey regkey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(key);
                string ns = regkey.GetValue("NameServer").ToString();
                regkey.Close();
 
                if (ns.Trim() != "") {
                    return false;
                }else{
                    return true;   
                }
            }
        }
        return false;
    }
posted by なまい at 10:00| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月10日

[WMI] DNSサーバアドレスを設定

指定したネットワークアダプタのDNSサーバアドレスを設定する。
DNSサーバアドレスを自動取得にするには、SetDNSServerSearchOrderメソッドのパラメータにnullを指定する。
サンプルでは第二引数、第三引数に空文字を指定した場合に自動取得に設定している。
    public void SetDNSAddress(string adapter, string primary, string secondary)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
 
                // DNSサーバのアドレス配列を生成
                object[] args = { new string[] { primary }, new string[] { secondary } };
 
                // 優先、代替のどちらも指定されていない場合は自動取得に設定する
                if ((primary == "") && (secondary == "")) { args = null; }
 
                uint res = (uint)mo.InvokeMethod("SetDNSServerSearchOrder", args);
                switch (res){
                case 0:
                    // 成功
                    break;
                case 1:
                    // 成功(再起動後に有効)
                    break;
                default:
                    // 失敗
                    break;
                }
            }
        }
    }
posted by なまい at 17:08| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年05月08日

[WMI] DNSサーバアドレス取得

指定したネットワークアダプタのDNSサーバアドレスを取得する。
第二引数に「0」を指定した場合は優先DNSサーバ、「1」を指定した場合は代替DNサーバを取得する。
    public string GetDNSAddress(string adapter, int index)
    {
        string query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
 
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                string[] dns = (string[])mo.Properties["DNSServerSearchOrder"].Value;
                return dns[index];
            }
        }
        return "";
    }
posted by なまい at 22:59| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする

2008年04月04日

[WMI] IPアドレスを設定

指定したネットワークアダプタにIPアドレス、サブネットマスクを設定する。
これするとDHCPは自動的に無効になる。
    public void SetStaticIPAddress(string adapter, string ip, string subnet)
    {
        string query = "";
        query = "SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled=TRUE";
        ManagementObjectSearcher mos = new ManagementObjectSearcher(query);
        ManagementObjectCollection moc = mos.Get();
        foreach (ManagementObject mo in moc) {
            if (mo.Properties["Caption"].Value.ToString() == adapter) {
                object[] args = { new string[] { ip }, new string[] { subnet } };
                uint res = (uint)mo.InvokeMethod("EnableStatic", args);
                switch (res){
                case 0:
                    // 成功
                    break;
                case 1:
                    // 成功(再起動後に有効)
                    break;
                default:
                    // 失敗
                    break;
                }
            }
        }
    }
posted by なまい at 23:00| Comment(0) | C# | このブログの読者になる | 更新情報をチェックする
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。