<   2010年 05月 ( 21 )   > この月の画像一覧
(.Net)iTextSharpを使ってPDFを出力する
iTextSharpというライブラリを使うと簡単にできるようです。

ダウンロードはhttp://sourceforge.net/projects/itextsharp/files/itextsharp/からできます。
なかなかクラスライブラリの詳しい説明をしてくれているサイトがないんですが、Vector:iTextSharp クラスライブラリリファレンスにて、ライブラリのリファレンスをヘルプ形式で提供してくれてます。
このリファレンスのおかげでほんと助かりました。

使い方の概要的なものは、CodeZine:iTextSharpを利用して.NETでPDF帳票を出力するがわかりやすいです。(途中までしか見えませんが。。。)

今回はテキストだけなので、かなり簡単にできました。

基本的には、Document インスタンスを生成し、PdfWriter.GetInstance で出力先を指定し、Document.Open → Document.Add で文字列追加 → Document.Close という流れです。

ハマったのは Font の指定でした。
上記のCodeZineに載っているように、直接フォントファイルへのパスを指定して、HG丸ゴシックを使いたかったんですが、下記のよう書いたらダメでした。

string systemRoot = Environment.GetEnvironmentVariable("SystemRoot");
Font fnt = new Font(BaseFont.CreateFont(systemRoot + @"\fonts\HGRSMP.TTF,0", BaseFont.IDENTITY_H, true), 24);

で、リファレンスを見てると、FontFactoryクラスを使うと簡単にできることが判明。
下記のような感じです。(C#)

Font fntNormal = FontFactory.GetFont("HG丸ゴシックM-PRO", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 16);
Font fntBlue = FontFactory.GetFont("HG丸ゴシックM-PRO", BaseFont.IDENTITY_H, 20, Font.NORMAL, iTextSharp.text.BaseColor.BLUE);
fntBlue.SetColor(255, 0, 0); //カラーを変更


全体としては下記のような感じです。(C#)

using iTextSharp.text.pdf;
using iTextSharp.text;
 
try
{
 
Document mDoc = new Document();
//font定義
FontFactory.RegisterDirectories();
Font fntNormal = FontFactory.GetFont("HG丸ゴシックM-PRO", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED, 22);
Font fntBlue = FontFactory.GetFont("HG丸ゴシックM-PRO", BaseFont.IDENTITY_H, 20, Font.NORMAL, iTextSharp.text.BaseColor.BLUE);
 
//保存先指定
PdfWriter.GetInstance(mDoc, new FileStream(@"c:\a.pdf", FileMode.Create));
 
//ドキュメント開く
mDoc.Open();
//データセット
mDoc.Add(new Paragraph("テストテスト", fntNormal));
mDoc.Add(new Paragraph("あいうえお", fntBlue));
fntBlue.SetColor(255, 0, 0);
mDoc.Add(new Paragraph("かっきくけこ", fntBlue));
mDoc.Add(new Paragraph(strInfoPasswd, fntNormal_middle));
mDoc.Add(new Paragraph(" " + user.Password, fntRed));

//ドキュメント閉じる
mDoc.Close();
 
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
}

[PR]
by jehoshaphat | 2010-05-31 23:06 | .Net開発 | Trackback | Comments(0)
(.Net,ADSI)グループにユーザアカウントを追加する
ADSIを使って、.Net からActiveDirectoryのユーザアカウントをグループに所属させる方法です。
下記のコードでできます。(C#)

/// <summary>
/// グループにユーザを追加
/// </summary>
/// <param name="strGroupPath">グループのパス(LDAP://ドメインコントローラ名/CN=グループ名,CN=Users,DC=domainname,DC=jp)</param>
/// <param name="strMemberPath">追加するユーザの識別名(CN=hoge,CN=test02,DC=domainname,DC=jp)</param>
public void AddMemberToGroup(string strGroupPath,string strMemberPath)
{
//Pathからグループオブジェクト取得
DirectoryEntry dEntGrp = new DirectoryEntry(strGroupPath, @"cn=administrator,DC=hogehoge,DC=jp", "1234");
//グループにメンバ追加
dEntGrp.Properties["member"].Add(strMemberPath);
//コミット
dEntGrp.CommitChanges();
}


参考:
MSDN:グループへのメンバの追加
[ADSI] Groupを作成し、Groupにメンバーを追加する - ComponentGeek Article これの2の方法を使いました。
[PR]
by jehoshaphat | 2010-05-31 22:48 | .Net開発 | Trackback | Comments(0)
バッチファイルでフォルダ内の再帰処理
複数のユーザが使ってる Windows XP で各ユーザの Application Data 内に特定のフォルダが無ければコピーしたいという要件があります。

で、そのような処理はバッチファイルで for in do 句でループ処理を行うと可能なようです。

下記のような例となります。
rem 各ユーザプロファイルのフォルダを探す
for /D %%i in ("%SystemDrive%\Documents and Settings\*") do (
rem echo %%i

rem xxxの設定フォルダが無ければ
IF NOT EXIST "%%i\Application Data\xxx" (
xcopy "C:\xxx" "%%i\Application Data\" /e /c /q /y /i
)
rem デスクトップのショートカット削除
DEL /Q "%%i\デスクトップ\*xxx*.lnk"
)


参考:
碧落 - 知られざるバッチファイル
バッチメモ(Hishidama's bat-file Memo)
[PR]
by jehoshaphat | 2010-05-31 22:13 | 豆知識 | Trackback | Comments(0)
Just-In-Time デバッガが鬱陶しいので無効にした

PC起動時に毎回といっていいほど、Just-In-Time デバッガが出てきます。デバッガしないを選択してもまた出てきます。
どうやら、DELLのサポートツールのVBScriptがエラーが吐いてるっぽいんですが。。
ほんとはなんでエラーが出てるのか調べる必要があると思うんですが、時間もないんでデバッガを無効にすることにしました。

下記のレジストリ値を削除すればいいようです。


HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AeDebug\Debugger


.Net Frameworkの方にも消すべきレジストリ値があるようですが、自分の環境の場合は有りませんでした。
が、参考までに、下記の値があれば消す必要があるようです。

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\DbgManagedDebugger


参考:
てすとぶろぐ: JITデバッガの無効化
JIT デバッガのレジストリ - Lunatic Sol
[PR]
by jehoshaphat | 2010-05-26 21:51 | 豆知識 | Trackback | Comments(1)
WSHでWScript.Shellオブジェクトを作成しようとするとエラー
(OSはXP SP3です。)

VBScriptを使って下記のように WScript.Shellオブジェクトを作成しようとしてました。

Set WshShell = CreateObject("WScript.Shell")
WScript.Echo "メモ帳を起動します。"
WScript.Run "notepad.exe"

ところが、こんなエラーが出ます。
ActiveXコンポーネントはオブジェクトを作成できません。

WScript.Shell はWindowsScriptの基本的オブジェクトなので作成できないのはおかしいです。

多分、WSH 自体が逝ってるのかと思って再インストールを試みました。

下記VBScriptで確認するとバージョンが5.7だったので、MSのダウンロードセンターから5.7をダウンロードしました。
WScript.Echo WScript.Version 'バージョン確認


しかし、インストーラを実行すると既に最新版入ってるからダメだ と怒られます。

それで、ひとつ古いバージョンの5.6をMSのダウンロードセンターからダウンロードして、インストールしてみました。
これだと問題なくインストールできます。

これで、CreateObject("WScript.Shell") を行うと問題なく処理が実行できます。

その後、WindowsUpdateをかけると、バージョンが 5.7 に上がってました。
この状態でも WScript.Shell のオブジェクト作成はできました。

結局原因はわかりませんでしたが、一旦5.6を入れ直して、Windows Update すればいいということですね。
[PR]
by jehoshaphat | 2010-05-26 21:50 | 豆知識 | Trackback | Comments(0)
WSHでインストール済みソフトを列挙
PC起動時に、ドメインに参加しているクライアントPCのインストール済みソフトを列挙し、サーバの共有フォルダにテキストファイルで落とすという方法を考えています。

グループポリシーで設定をしたいので、WSH(Windows Script Host)を使ってみることにしました。

実はWSH使うのは初めてなんで、@IT:WSHを始めようをまず読んでみます。

WSHのスクリプトは、よく耳にするVBSciprtでかけるみたいです。

で、GUI版(wscript.exe)とCUI版(cscript.exe)があるようです。
コマンドプロンプトでWSH実行するときに使い分けれるようです。

wscript test.vbs GUI版で実行
cscript test.vbs CUI版で実行

GUI,CUI版の違いについては、WscriptとCscriptの違い-WSH@Workshopが参考になります。


で、本題のインストールソフト列挙ですが、最初試したの下記のMicrosoftにあったサンプルです。
MS TechNet:インストール済みソフトウェアの列挙
WMIで列挙する方法ですね。

しかし、実行すると For ループの Next で (null): 0x80041001 のエラーとなります。

MS TechNet:Windows Management Instrumentation の秘密 トラブルシューティングとヒントを見てみたところ、クラス接続失敗してるっぽいです。

とりあえずデバッグしてみることに。。。
WSH のデバッグ方法とOS側設定 更新版 - しおそるとと、WSH のデバッグ方法とOS側設定 - しおそるとを見て、Windows Script Debuggerを入れてみました。

Windows Script Debuggerはここからダウンロードできるようです。

Windows Script Debuggerを起動して、コマンドプロンプトより、//x オプション付きで実行するとデバッグができるようです。

D:\>cscript //x test.vbs

しかし、確かにデバッグできるようになりましたが、コマンドウィンドウで "? 変数" とすると固まるし、null が発生する箇所に来ても固まります。
Office についてくるらしい Microsoft Script Editor でも試してみましたが、IDEは立ち上がりますがデバッガが起動しません。

仕方ないからWMI使わない方法にしました。
人力検索はてなを参考にしてレジストリから取得する方法です。

ほぼ、はてな であがってたコードそのままですが、実行するとDドライブ直下にホスト名のテキストファイルでインストールソフトのリストが列挙されます。


Option Explicit
On Error Resume Next
 
Const HKEY_LOCAL_MACHINE = &H80000002
 
Dim objRegProv, ccSubKeys
Dim strComputer, sytKey, strSubKey, dwVal
Dim strDisplayName, strParentKeyName, dwSystemComponent
Dim objTextFile
Dim objFSO
Dim computername
Dim objNetWork
 
'WScript.CreateObject("WScript.Network") がダメなときは日付をファイル名に持つ
computername =Year(NOW()) & _
Right("0" & Month(NOW()), 2) & _
Right("0" & Day(NOW()), 2) & _
Right("0" & Hour(NOW()), 2) & _
Right("0" & Minute(NOW()), 2) & _
Right("0" & Second(NOW()), 2)
'コンピュータ名取得
Set objNetwork = WScript.CreateObject("WScript.Network")
computername = objNetWork.ComputerName
 
'保存するためのファイルオブジェクト
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.CreateTextFile("d:\" & computername & ".txt", True)
 
'レジストリ操作オブジェクト
strComputer = "."
Set objRegProv = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
 
'レジストリからインストール情報取得
sytKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Call objRegProv.EnumKey(HKEY_LOCAL_MACHINE, sytKey, ccSubKeys)
For each strSubKey in ccSubKeys
dwVal = objRegProv.GetStringValue(HKEY_LOCAL_MACHINE, sytKey & "\" & strSubKey, "ParentKeyName", strParentKeyName)
If dwVal <> 0 Then ' ParentKeyNameが無いものが対象(更新インストールではないもの)
dwVal = objRegProv.GetDWORDValue(HKEY_LOCAL_MACHINE, sytKey & "\" & strSubKey, "SystemComponent", dwSystemComponent)
If dwVal <> 0 Or dwSystemComponent = 0 Then ' システムフラグが無いまたはゼロのものが対象
dwVal = objRegProv.GetStringValue(HKEY_LOCAL_MACHINE, sytKey & "\" & strSubKey, "DisplayName", strDisplayName)
If dwVal = 0 And strDisplayName <> "" Then ' 表示名があるものが対象
objTextFile.WriteLine strDisplayName
End If
End If
End If
Next



参考:
猫科研究所(felid labo) - WSHのデバッガ
[PR]
by jehoshaphat | 2010-05-26 21:47 | 豆知識 | Trackback | Comments(0)
コンテキストメニューにコマンドプロンプトを追加する
PCセットアップすると最初にするくせによく忘れるのでメモ。。
エクスプローラでフォルダ右クリック時にコマンドプロンプトを追加する方法です。

下記のレジストリを追加すればOKです。

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\OpenNew]
@="コマンドプロンプト"

[HKEY_CLASSES_ROOT\Directory\shell\OpenNew\Command]
@="cmd.exe /k \"cd %L\""


参考:
@IT:Windows TIPS -- Tips:エクスプローラでカレント・フォルダを選択してコマンド・プロンプトを開く
不定期メモ: エクスプローラのコンテキストメニューにコマンドプロンプトを追加する UNC対応の方法も書かれてます。
[PR]
by jehoshaphat | 2010-05-23 07:45 | 豆知識 | Trackback | Comments(0)
ターミナルサービス使用中に、IE8でファイルがダウンロードできない
ターミナルサービスでWindowsServer2003を使ってて、IE8でファイルのダウンロードができないという現象が発生しました。
IEのキャッシュ等を消したりいろいろしたんですが、全然ダメです。

で、調査した結果 IME の不具合ということが分かりました。
下記のMSサポートに対応が載せられています。
MSサポート:Windows Server 2003 または Windows XP を実行しているコンピューターで、Windows Internet Explorer を使用してファイルをダウンロードできないことがある

対策としては、修正パッチを当てる方法と、コンパネから「地域と言語のオプション」→「言語タブ」の「詳細」→「テキストサービスと入力言語」画面の「詳細設定」タブの「詳細なテキスト サービスをオフにする」にチェックを入れるといいようです。
ただ、これはユーザ毎の設定なので、多人数で利用するターミナルサーバの場合は、パッチを当てたほうが賢明ですね。

XPのパッチは上記のサポートページに有るんですが(XP SP3でも修正済みですしね)、WindowsServer2003のパッチは別途リクエストしないといけないようです。
ここからOSを選択し、メールアドレスを入れるとパッチがダウンロードできるようです。


しかし、IME というより、テキストサービスは結構不具合が多いようですね。
@IT:Tips:ctfmon(テキスト・サービス)を自動起動しないようにするにもテキストサービスによる不具合が列挙され、無効にしておくように勧められています。

最近は IME から Google 日本語入力に乗り換えてる三流プログラマでした。。。
(しかし、Google日本語入力とかでてくるとますますATOKの居場所がなくなるような気が。。。)
[PR]
by jehoshaphat | 2010-05-23 07:43 | サーバがらみ | Trackback | Comments(0)
(C++)ファイルの存在チェックを行う
Win32 API でファイル存在チェックを行う方法です。

PathFileExists( ファイル名 )関数を使えばいいようです。
存在すれば true ,しなければ false ( C的には1かそれ以外か) が返るようですね。

参考:
WINDOWS忘却録 PathFileExists -ファイルの存在を調べるAPI-
[MFC/Win32API] ファイル・フォルダの存在チェック - かえでのWebログ
[PR]
by jehoshaphat | 2010-05-23 07:41 | C/C++開発 | Trackback | Comments(0)
(C++)環境変数のパスを展開する
%systemroot% や %programfiles% との環境変数パスをC++で展開する方法です。

Win32 API の ExpandEnvironmentStrings 関数を使えばいいようです。
注意点は %appdata% だと %%appdata%% というように%でエスケープしないといけないという点です。

こんな感じで使います。

WCHAR CheckFileName[1024];
swprintf( CheckFileName , _T("%%APPDATA%%\\test.txt") );
WCHAR CheckFileName2[1024];
ExpandEnvironmentStrings( CheckFileName ,CheckFileName2,sizeof( CheckFileName2 ));

なお、各OSの環境変数パスの一覧はVistaとXPにおけるパス関係のユーザ環境変数の相違。 - 片っ端から忘れていけばいいじゃない。できれいにまとめられています。
[PR]
by jehoshaphat | 2010-05-20 23:49 | C/C++開発 | Trackback | Comments(0)