USB を Eject するソースコードの取得と実装

  C# 用 と C++ 用を CodeProject より取得



サインアップが必要ですが、損は無いですね。時々お世話になってます。

↓C#
http://www.codeproject.com/KB/system/usbeject.aspx
( C# 用と言っても、ライブラリなので、ビルドしてしまえば VB.NET からも普通に使えます )

↓C++
http://www.codeproject.com/KB/system/RemoveDriveByLetter.aspx

C# 用は、Download source files - 106.9 Kb に、ライブラリ込みでデモアプリが入って
ますが、何も考えずに C# のクラスライブラリプロジェクトにインポートしてビルドし、
Windows アプリケーションプロジェクトから参照して使います

( ここでは、VB.NET から使ってみました )

  
Imports UsbEject.Library

Public Class Form1

	Private Sub Button1_Click(ByVal sender As System.Object, _
	ByVal e As System.EventArgs) Handles Button1.Click

		Dim volumeDeviceClass As New VolumeDeviceClass()
		For Each device As Volume In volumeDeviceClass.Devices
			' is this volume on USB disks? 
			If Not device.IsUsb Then
				Continue For
			End If

			' is this volume a logical disk? 
			If (device.LogicalDrive Is Nothing) OrElse _
			(device.LogicalDrive.Length = 0) Then
				Continue For
			End If

			MessageBox.Show(device.LogicalDrive)
			' allow Windows to display any relevant UI 
			device.Eject(False)
		Next

	End Sub
End Class
  

もとのページにあるサンプルは、C# で書かれてましたが、そのままでは芸が無いので
http://labs.developerfusion.co.uk/convert/csharp-to-vb.aspx でコンバート
して使用しています

FalseTrue に変えると、「安全に取り外す事ができます」というダイアログが表示されます。
( XP だと、バルーンですね )

device.LogicalDrive には、"E:" という形のドライブレターが入っています

つまり、非常に使いやすい形になっていますので、利用するのは簡単だと思います。
実行には、すこし時間がかかります。デバイスリストを全て取得しているせいだとは思いますが、
これは、WMI スクリプトで一覧取得した時もそうでした。

まあ、USB という形態から考えても、そう急ぐ必要性も無いでしょう。



  C++ 用



これは、コンソールアプリケーション用のプロジェクトで、引数に E というようなドライブを渡すと
そのドライブを処理してくれます。コメントになってますが、C# と同じようにメッセージボックス(XPはバルーン)を
出すようにもできます。( そのままでは出ません )

  
res = CM_Request_Device_EjectW(DevInstParent, &VetoType, VetoNameW, MAX_PATH, 0);
//res = CM_Request_Device_EjectW(DevInstParent, NULL, NULL, 0, 0); // with messagebox (W2K, Vista) or balloon (XP)
  

これは、USB の中に置いて、VBScript から自分自身を取り外すようにできます。

また、同様の機能を持ったフリーソフトは以下のようなものがあります( 使った事無いのでよく解りません )
http://homepage3.nifty.com/yamakox/UnplugDrivePortable/index.html



  C++ 用のソースコードを Framework 用のクラスライブラリとしてビルドする

↓Framework 用 クラスライブラリのダウンロード

http://lightbox.on.coocan.jp/download/Uwe_Sieber.lzh


もともとが、昔ながらの「マルチ バイト文字セットを使用する」というオプションでビルドされるものですから、
それに合わせた方法で乗せ変えます。当然「マルチ バイト文字セットを使用する」ものとして、コードを書きます。
( クラスライブラリは、デフォルトで Unicode になっていますから、変更して下さい )

ヘッダーファイルは以下の二つを追加して下さい
comdef.h
vcclr.h

( comdef.h を書けば、windows.h は書かなくても OK です )

↓実際はこんなかんじ
  
#pragma once
#pragma comment( lib, "setupAPI.lib" )

#include <stdio.h>

#include <comdef.h>

#include <Setupapi.h>
#include <winioctl.h>
#include <winioctl.h>
#include <cfgmgr32.h>
#include <vcclr.h>
  


  
public:
	int eject( System::String ^drv ) {

		pin_ptr<const wchar_t> wch = PtrToStringChars(drv);
		_bstr_t cstr = wch;
		char *ch = (char *)cstr;

		char szRootPath[] = "X:\\";   // "X:\"  -> for GetDriveType
		szRootPath[0] = ch[0];

		char szDevicePath[] = "X:";   // "X:"   -> for QueryDosDevice
		szDevicePath[0] = ch[0];

		char szVolumeAccessPath[] = "\\\\.\\X:";   // "\\.\X:"  -> to open the volume
		szVolumeAccessPath[4] = ch[0];
  

上記は、eject メソッドの入り口の部分ですが、引数が System::String ^drv として、
Framework 仕様になっています。

それをまず、wchar_t * に変換して、_bstr_t オブジェクトを作成します。そうすれば、char * はキャストするだけで
手に入りますので、そのままコードが移行可能となります

以下は、VB.NET からの呼び出し部分です

  
Dim a As New test_class.Class1()
a.eject("E")
  





  【付録】 既存の文字列と Framework 文字列の相互変換のサンプル

  
#include "stdafx.h"
#include <comdef.h>
#include <vcclr.h>

using namespace System;

int main(array<System::String ^> ^args)
{

	_bstr_t a = "日本語表示";

	String ^x;

	x = gcnew String((const wchar_t *)a);

	Console::WriteLine(args[0]);
	Console::WriteLine(x);

	printf( "%s\n", (char *)a );

	pin_ptr<const wchar_t> wch = PtrToStringChars(args[0]);

	_bstr_t b = wch;
	printf( "%s\n", (char *)b );

	Console::ReadLine();

	return 0;

}
  

_bstr_t の仕様により、_bstr_t a = "日本語表示"; の文字列は、Unicode でも、マルチバイトでも正しく動きます。










  infoboard   管理者用   
このエントリーをはてなブックマークに追加





フリーフォントWEBサービス
SQLの窓WEBサービス

SQLの窓フリーソフト

素材

一般WEBツールリンク

SQLの窓

フリーソフト

JSライブラリ