親牛の開発日記

ぼけ防止するため、開発メモを残そう

Windows Shell 開発覚書

■パスからITEMIDLISTを取得するには

 SHParseDisplayName

 例:「c:\temp\my.txt」ファイルのITEMIDLISTを取得するとしよう

 LPITEMIDLIST pItemIDLIST = NULL;

 HRESULT hr = SHParseDisplayName(file, NULL, &pItemIDLIST, 0, NULL);

 if (SUCCEEDED(hr)) {

  CoTaskMemFree(pItemIDLIST); // 使い切ったら、開放すべき。

 }

CreateFileでAVStream minidriverから HANDLEの取得方法

マイクロソフトさんのドライバサンプルを例にする

github.com

ドライバに「コマンド(IOCTL)」を送る(DeviceIoControlを利用)際に、予め「CreateFile」で対象ドライバのハンドル(HANDLE)取るべき。

CreateFileの1つ目の引数にドライバから公開した「Symbolic Link」を使えばいいですが、AVStream minidriverみたいなWDMドライバだと、「IoCreateSymbolicLink」を使えないため、代わりに「IoRegisterDeviceInterface」を利用する。

サンプルでの実装だと、

①「device.cpp」の先頭に、以下の宣言を追加

const GUID IF_NAME_GUID =
{ 0xe7b615ba, 0x1909, 0x40a3,{ 0xbd, 0x24, 0xb2, 0x67, 0x14, 0xa6, 0x25, 0x52 } };

static UNICODE_STRING symbleName;

IF_NAME_GUIDはVisual Studio のツール「GUIDの作成」を利用し、作成する。

 

②「device.cpp」のCCaptureDevice::DispatchCreate静的関数の中に以下のソースを追加

...
if (!CapDevice) {
    ...
}
else {
    KsAcquireDevice(Device);
    ...
    if (NT_SUCCESS(Status)) {
        Status = IoRegisterDeviceInterface(Device->PhysicalDeviceObject

            , &IF_NAME_GUID, NULL, &symbleName);
    if (NT_SUCCESS(Status)) {
        DbgPrint("[avshws::DriverEntry] %S", symbleName.Buffer);

        Status = IoSetDeviceInterfaceState(&symbleName, TRUE);
    }
}

KsReleaseDevice(Device);
...
}
...

IoSetDeviceInterfaceStateルーチンの呼出しは設定したSymbolic Linkを有効させるため。

 

 

そうすると、以下のようなSymbolic Linkが出来上がり。

\\?\Root#UNKNOWN#0000#{GUID}

できたSymbolic Linkそのまま使えないので、下記の形にしてください。

\\?\Root#UNKNOWN#0000#{GUID}\GLOBAL

 ドライバを開く

HANDLE file = CreateFile(L"\\\\?\\Root#UNKNOWN#0000#{GUID}\\GLOBAL"

    ,GENERIC_READ | GENERIC_WRITE

    , FILE_SHARE_READ | FILE_SHARE_WRITE

    , NULL

    , OPEN_EXISTING

    , 0

    , NULL);

 

==以上==

Javaアプリのリソースファイル(データ)を取得する際にリソースパスについ

・リソースの取得

すべてのJavaアプリに対し、下記3つのリソースがあれば

src

  main

     java

       com

          pkg

             Main.java

             main.properties

     resources

        template

            1.html

        my.properties

 

それぞれの取得に以下のパスで行う。

・main.properties

ClassLoader.getSystemResource("com/pkg/main.properties")

・1.html

ClassLoader.getSystemResource("template/1.html")

・my.properties

ClassLoader.getSystemResource("my.properties")

ではなぜなのか?実際にコンパイルしたフォルダの構成にかかってる

上記のソースフォルダツリーであれば、コンパイル後に以下のアウトプットをできる

classes

    com

      pkg

         Main.class

         main.properties

    template

        1.html

    my.properties

つまり、リソースのパスはコンパイル後の場所と関係していることが分かりました。

 

 2018/06/11 IntelliJの中に、リソースフォルダの追加方法

stackoverflow.com

Visual Studio CodeでNODE-REDのデバッグ方法

NODE-REDのインストールは、

github.com

で書いてある「Developer」方法でスラスラやればいい。

 

もちろん誰よりも先にNodeJSのインストールを済ませる。

 

NODE-REDを起動する際に以下のコマンドラインで行ってください。

<node-red実施にインストールされたフォルダ>$ node --inspect-brk red.js

※ポイントは「--inspect-brk」オプションを付けること。当方のNodeJSのバージョンはv8.11.1、古い「--debug-brk」で付けると無視される。

 

上記の設定で問題なく起動すると、以下のメッセージを表示される。

Debugger listening on ws://127.0.0.1:9229/ee6542cb-bd43-46e5-b7ce-c681999f11db
For help see https://nodejs.org/en/docs/inspector

 それから、Visual Studio Codeの登場

1.まず、node-redのインストール先フォルダを開く

2.デバッグ設定

f:id:itroad:20180422175855p:plain

3.上記設定を終わったら、アタッチしてデバッグを行いましょう。

 

==以上==

 

C#から文字列の配列をC/C++ DLLへの渡し方

■ネイティブ関数の引数が「char**」の場合

C関数

void init(int argc, char** argv);

C#

[DllImport("XXXXX.dll")]
public static extern int init(int argc, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex =1)]string argv);

これは無難だろう

 

■ネイティブ関数の引数が構造体であって、その中に「char**」があった場合

C構造体

struct ARGS

{

 int argc;

 char** argv;

};

void init(struct ARGS * pArgs);

 

C#

public struct ARGS
{

int Argc;
IntPtr Argv;

public ARGS(string argv)
{
  Argc = argv.Length;
  Encoding encoding = Encoding.GetEncoding(932);
  List<string> list = new List<string>(argv);
  Argv = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)) * list.Count);

  for (int index = 0; index < list.Count; index++)
   {
      int len = encoding.GetByteCount(list[index]) + 1;
      IntPtr point = Marshal.AllocCoTaskMem(len);
      Marshal.Copy(encoding.GetBytes(list[index]), 0, point, len - 1);

      Marshal.WriteByte(point, len - 1, 0);

      Marshal.WriteIntPtr(Argv, index * Marshal.SizeOf(typeof(IntPtr)), point);
   }
}

}

[DllImport("XXXXXX.dll")]
public static extern int Init(ref ARGS args);