<   2008年 09月 ( 8 )   > この月の画像一覧
(VB.Net)[補足2].NetからのPDFファイル印刷方法
この記事は(VB.Net)[補足].NetからのPDFファイル印刷方法の追記情報です。

ジョブやキューはループの中でまわしてもそのままではステータスは最新のものにならないようです。
PrintQueue.Refresh() や PrintSystemJobInfo.Refresh() というメソッドを実行することで、最新情報が取得できるようです。
なので、上記のコードの中に Refresh() メソッドが必要になりますね。
また、PrintSystemJobInfo.JobStatus プロパティや PrintQueue.QueueStatus プロパティは複数のステータスを保持するみたいなので、JobStatus、QueueStatusプロパティに取り出したいプロパティの論理積をとってやる必要があることがMSDNのここに書かれていました。

ということで、ステータスを見るとこは下記のようなコードになると思います。

'ジョブが印刷中,印刷完了されていればスプールが終わっているはずなので処理正常終了
If (jobNow.JobStatus And PrintJobStatus.Completed) = PrintJobStatus.Completed _
OrElse (jobNow.JobStatus And PrintJobStatus.Deleted) = PrintJobStatus.Deleted _
OrElse (jobNow.JobStatus And PrintJobStatus.Deleting) = PrintJobStatus.Deleting _
OrElse (jobNow.JobStatus And PrintJobStatus.Printed) = PrintJobStatus.Printed _
OrElse (jobNow.JobStatus And PrintJobStatus.Printing) = PrintJobStatus.Printing _
OrElse (jobNow.JobStatus And PrintJobStatus.Retained) = PrintJobStatus.Retained Then
'ループ終了
Exit While
End If
'ジョブがなんらかのエラーがあったとき。
If (jobNow.JobStatus And PrintJobStatus.Error) = PrintJobStatus.Error Then
Throw New PamTrWarningException("印刷に失敗しました。印刷ジョブはエラー状態にあります。")
End If
If (jobNow.JobStatus And PrintJobStatus.Offline) = PrintJobStatus.Offline Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタはオフラインです。")
End If
If (jobNow.JobStatus And PrintJobStatus.PaperOut) = PrintJobStatus.PaperOut Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタが必要な用紙サイズに適合していません。")
End If
If (jobNow.JobStatus And PrintJobStatus.UserIntervention) = PrintJobStatus.UserIntervention Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタは、エラー状態を修正するためにユーザーの操作を必要としています。")
End If
If (jobNow.JobStatus And PrintJobStatus.Paused) = PrintJobStatus.Paused Then
Throw New PamTrWarningException("印刷に失敗しました。印刷ジョブは一時停止されます。")
End If
If (jobNow.JobStatus And PrintJobStatus.Blocked) = PrintJobStatus.Blocked Then
Throw New PamTrWarningException("印刷に失敗しました。キュー内にあるこのジョブよりも優先される印刷ジョブが原因と考えられるエラーが発生したため、印刷ジョブがブロックされました。")
End If
 
 
 
'キューになんらかのエラーがあったとき
If (que.QueueStatus And PrintQueueStatus.ServerUnknown) = PrintQueueStatus.ServerUnknown Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタはエラー状態にあります。")
End If
If (que.QueueStatus And PrintQueueStatus.OutOfMemory) = PrintQueueStatus.OutOfMemory Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタに使用可能なメモリがありません。")
End If
If (que.QueueStatus And PrintQueueStatus.UserIntervention) = PrintQueueStatus.UserIntervention Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタは、エラー状態を修正するためにユーザーの操作を必要としています。")
End If
If (que.QueueStatus And PrintQueueStatus.PagePunt) = PrintQueueStatus.PagePunt Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタで現在のページを印刷できません。")
End If
If (que.QueueStatus And PrintQueueStatus.NoToner) = PrintQueueStatus.NoToner Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタのトナーがありません。")
End If
If (que.QueueStatus And PrintQueueStatus.Offline) = PrintQueueStatus.Offline Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタはオフラインです。")
End If
If (que.QueueStatus And PrintQueueStatus.PaperProblem) = PrintQueueStatus.PaperProblem Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタの用紙が原因で、未定義のエラーが発生しています。")
End If
If (que.QueueStatus And PrintQueueStatus.PaperOut) = PrintQueueStatus.PaperOut Then
Throw New PamTrWarningException("印刷に失敗しました。現在の印刷ジョブに必要な種類の用紙がプリンタにセットされていないか、または用紙切れです。")
End If
If (que.QueueStatus And PrintQueueStatus.PaperJam) = PrintQueueStatus.PaperJam Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタの用紙が詰まっています。")
End If
If (que.QueueStatus And PrintQueueStatus.Error) = PrintQueueStatus.Error Then
Throw New PamTrWarningException("印刷に失敗しました。プリンタがエラー状態のため印刷できません。")
End If
If (que.QueueStatus And PrintQueueStatus.Paused) = PrintQueueStatus.Paused Then
Throw New PamTrWarningException("印刷に失敗しました。印刷キューが一時停止されています。")
End If


ところで、このステータスですが、どこまで正確な情報が取れるかが不明です。
あまりステータステストをしていないのですが、Windowsのプリンタのキューをオフラインにしてもオフラインになっていませんでした。キューの一時停止はキューのステータスでとれたのですが。もう少し調査が必要ですね。
[PR]
by jehoshaphat | 2008-09-22 14:15 | .Net開発 | Trackback | Comments(0)
(SQL)時間、分を別列に分けた仕様の時に、時間文字列を生成する方法
時間という情報を格納するのに datetime 型の時間の部分だけに入れることが多いかもしれませんが、24時を超えた時間を「25」という値で持ちたい時があるかもしれません。
(まあ、datetime で日付を+1して保存するという方法もあるかもしれませんが。。)
というわけで、 "Hour"列と"Minute"列をint型で用意して、それに時間を保存するパターンについてのノウハウです。

DMBMSはSQL Server2005です。
この状態でSQLで時間を条件にしたい時、"Hour"列と"Minute"列を文字列(varchar)に直して比較したいわけですが、この文字列に直すというのが結構曲者でした。

普通に

SELECT
STR( Hour , 2 ) + ':' + STR( Minute , 2) + ':00'

とすると、一桁の数値の場合
9:1:00
という風になってしまいます。

ということで、"Hour"列と"Minute"列の値が一桁の場合に0埋めするようにしました。

参考にさせてもらったのはこちらです。
0埋めする方法として下記のように記されていました。
------------------------------
--0埋めを行う(例、10桁)

SELECT
RIGHT(REPLICATE('0', 10) + REPLACE(STR(@Number), ' ', ''), 10)

--結果: '0000000123'
------------------------------

なにやら関数だらけですが、ようは下記のような流れになっています。
まず REPLICATE('0', 10)。結果は "0000000000" になります。
これに STR(@Number) で数値を文字列化。このとき、STRの第2引数に値を入れないと自動的に空白の入った10桁の文字列ができます。@Numberが"3"だとすると結果は" 123"となります。
この空白の入った文字列から空白除去するために REPLACE 関数で空白を空文字に置換します。この結果は"123"となります。
"+"記号はSQL Serverでは文字列連結演算子なので、ここまでの結果は "0000000000123"となります。
最後に仕上げで RIGHT 関数で右から10桁切り取ります。
これでめでたく"0000000123"という結果が返るわけです。

さて、このコードを見た同僚はもっとシンプルにできるということで、下記のようなSQLを書いてくれました。
SELECT
RIGHT('0000000000' + LTRIM(STR(@Number)), 10)

ようは空白除去に LTRIM 関数を、そして0埋めよう文字列は最初から''で用意しておくというわけです。

この方法で、Hour"列と"Minute"列を0埋めあり文字列に直すSQLはこうなりました。

SELECT
RIGHT('00' + LTRIM(STR( Hour )), 2) + ':' + RIGHT('00' + LTRIM(STR( Minute )), 2) + ':00'

あとはこの形式(hh:mm:ss)に直した比較用変数で普通に比較できます。
例:

declare @Time DateTime
SET @Time='13:00:00'
 
SELECT *
FROM TABLE
WHERE RIGHT('00' + LTRIM(STR( Hour )), 2) + ':' + RIGHT('00' + LTRIM(STR( Minute )), 2) + ':00' > CONVERT(varchar, @Time, 108)


ちなみにこれはSQL Server専用です。
各DBMSでの文字列操作関数の違いはこちらに丁寧にまとめられています。
これを見ると文字列の連結(結合)もDBMSによって随分仕様が違うんですね。。
[PR]
by jehoshaphat | 2008-09-19 17:01 | SQL | Trackback | Comments(0)
(VB.Net)[補足].NetからのPDFファイル印刷方法
以前に(VB.Net).NetからのPDFファイル印刷方法という記事を書きましたが、それの追記です。

実はあの方法だと1つ問題が生じることが分かりました。
それはプロセスの終了方法です。

'プロセス終了
pro.WaitForExit(5000)
pro.Kill()

というやり方は時間指定で、5秒待ったらAdobeReaderのプロセスを殺すというアプローチをとっていますが、この時間が環境によってまちまちなのです。

たとえばAdobeReader自体重いアプリケーションに入るのでスペックが低いマシンだとプロセス立ち上がり印刷スプールが終わるまで何十秒もかかるかもしれません。
ということは5秒でプロセス殺すと結局印刷できないことになります。逆に速いマシンでは数秒で片付くでしょう。

まあ待ち時間をかなり長くするというのも手なのでしょうが、それは嫌だったので、実際にAdobeReaderが印刷ジョブにスプールし終わったことを確認してプロセス終了するという方法を考えてみました。

なお、.Net2.0のFCL(クラスライブラリ)には印刷キューやプリンタ情報関連を操作するクラスがほとんどありません。
Win32API使うしかないのかと思っていたところ、.Net3.0から追加された System.Printing.dll を参照設定で読み込めばVisualStudio2005(.Net2.0)でも印刷関連の各種情報を操作できることが分かりました。

ということで、VisualStudio2005で以下のソースを実行するには.Net3.0以上のインストールと System.Printing.dll 参照設定が必要になると思います。
(インストールしてなくても、PresentationCore.dll , System.Printing.dll さえ用意すればいいみたいですが。。)

'Imports System.Printing が必要!
 
Private Function PrintPdf() As Boolean
'====レジストリからAcrobat,AcrobatReaderのパス取得====

Dim strRegPath As String
Dim rKey As RegistryKey
 
'キーを取得(最初にAcrobat,だめならAdobeReader)
strRegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Acrobat.exe"
rKey = Registry.LocalMachine.OpenSubKey(strRegPath)
If rKey Is Nothing Then
strRegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe"
rKey = Registry.LocalMachine.OpenSubKey(strRegPath)
 
End If
 
'値(exeのパス)を取得(既定の値の場合は空文字指定)
Dim location As String
Try
'値(exeのパス)を取得(既定の値の場合は空文字指定)
location = DirectCast(rKey.GetValue(""), String)
Catch ex As NullReferenceException
Throw New ApplicationException("AcrobatもしくはAdobeReaderがインストールされていないため、PDFファイルの印刷ができません。")
Finally
'開いたレジストリキーを閉じる
rKey.Close()
End Try
 
'===Acrobatを起動し印刷===
Dim filepath As String = "D:\print_test.pdf"
Dim pro As New Process()
 
'.Net的書き方(C#でも可能な書き方)
'Acrobatのフルパス設定
pro.StartInfo.FileName = location
pro.StartInfo.Verb = "open"
'Acrobatのコマンドライン引数設定
pro.StartInfo.Arguments = " /n /t " + filepath
pro.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
'プロセスを新しいWindowで起動
pro.StartInfo.CreateNoWindow = True
 
'プリントサーバの情報取得
Dim prtSv As New LocalPrintServer()
'印刷キュー取得
Dim que As PrintQueue = prtSv.DefaultPrintQueue
 
'AdobeReaderプロセス起動して印刷
pro.Start()
 
 
'処理フラグ T:正常 F:異常
Dim blnRtn As Boolean = True
'ジョブ番号
Dim intJobNum As Integer
 
'ループ内での時間カウント
Dim intCnt As Integer = 0
'下記のループで待つ時間をミリ秒単位で指定
Dim intWatiMiliTime As Integer = 500
 
'PDFの印刷がキューに入るまで待つ。
While True
'指定ミリ秒待つ
Threading.Thread.Sleep(intWatiMiliTime)
intCnt += intWatiMiliTime
 
'1分以上たっていたら、印刷に問題があったことにして処理異常フラグを立てる
If intCnt > 60000 Then
blnRtn = False
End If
 
'キューが1つ以上
If que.NumberOfJobs > 0 Then
Dim jobList As New List(Of PrintSystemJobInfo)()
'印刷ジョブコレクション取得
For Each i As PrintSystemJobInfo In que.GetPrintJobInfoCollection
jobList.Add(i)
Next
'最新ジョブ名に".pdf"が含まれるとき、このプログラムから印刷キューに入れたと判断する。
If jobList(jobList.Count - 1).Name.EndsWith(".pdf", True, Nothing) Then
intJobNum = jobList(jobList.Count - 1).JobIdentifier
Exit While
End If
End If
End While
 
intCnt = 0
 
'指定されたジョブが印刷完了するまで待つ
While blnRtn
'指定ミリ秒待つ
Threading.Thread.Sleep(intWatiMiliTime)
intCnt += intWatiMiliTime
 
Dim jobNow As PrintSystemJobInfo
Try
'このプログラムから印刷キューに入れたジョブを取得
'(ループの中でキューからジョブを取得しないとJobStatusが更新されないので注意)
jobNow = que.GetJob(intJobNum)
Catch ex As Exception
'(すでに印刷が完了してジョブが破棄されたとき対策)
'異常フラグ立てループ終了
blnRtn = False
End Try
 
'ジョブが印刷中,印刷完了されていればスプールが終わっているはずなので処理正常終了
If jobNow.JobStatus = PrintJobStatus.Completed _
OrElse jobNow.JobStatus = PrintJobStatus.Deleted _
OrElse jobNow.JobStatus = PrintJobStatus.Deleting _
OrElse jobNow.JobStatus = PrintJobStatus.Printed _
OrElse jobNow.JobStatus = PrintJobStatus.Printing _
OrElse jobNow.JobStatus = PrintJobStatus.Retained Then
'ループ終了
Exit While
End If
 
'ジョブがなんらかのエラか、タイムアウト(1分)したなら処理異常終了
If jobNow.JobStatus = PrintJobStatus.Error _
OrElse jobNow.JobStatus = PrintJobStatus.Offline _
OrElse jobNow.JobStatus = PrintJobStatus.PaperOut _
OrElse jobNow.JobStatus = PrintJobStatus.UserIntervention _
OrElse intCnt > 60000 Then
'異常フラグ立てループ終了
blnRtn = False
End If
End While
 
'プロセス終了
pro.Kill()
 
Return blnRtn
End Function


特に後半部分が追加した、印刷ジョブの監視機能となります。
ただ、スプールが終わったかのジョブステータス判断等のif文は詳しく調べたわけでないので、正しくないかもしれません。
もっと綺麗な方法があるっていう人は情報ください。

まだ、System.Printing名前空間配下のクラスの情報がほとんど出回ってないんですよね。
まあ、MSDNにはこのライブラリのリファレンスがあるので、使い方はわかるんですが。。

ちなみにAPIを使ってプリンタや印刷関連の情報を取得する方法は結構出回ってます。下記リンク参照。
プリンタのポート、状態を取得する
MS: Visual Basic .NET アプリケーションから EnumJobs 関数を呼び出す方法
プリンタのプロパティだけを表示 (2)

追記:この方法ではジョブやキューの状態取得に問題があることが判明しました。
詳しくは(VB.Net)[補足2].NetからのPDFファイル印刷方法を参照。
[PR]
by jehoshaphat | 2008-09-12 15:53 | .Net開発 | Trackback | Comments(0)
大規模アプリケーション:GREEの事例
ITmediaに「大規模サイトの舞台裏:大規模SNSのボトルネックとソリューション 」という記事が出ていました。

GREEの事例が載せられており、DBアクセスのボトルネックをどのように解決しているか紹介されています。
これは非常に勉強になりました。

DBサーバを分散しているわけですが、いくつかのテーブルごとにデータベースを別々のサーバに分けてるのには驚きました。
理由は、分散ファイルシステムのように、DBのデータが別々のサーバにあっても使う側から見ると1つのデータベースとして見えるような仕組みがあるからだと思ったからです。
調べてみると、パーティショニング(DBを分散させて使う側が1つのDBとしてみる方法)はOracleとかDB2とかSQL Server(Enterprise)等のエンタープライズに特化したDBしか機能が搭載されていないようです。
ということは、この記事ででてたOSSのMySQLはそのような機能はないようです。(と思ってましたが、最新のMySQL5.1(今年リリース?)ではパーティショニングが搭載されたようです。)
テーブルごとに別々のサーバに分けてるということはSQL文で JOIN が使えないということです。

1年で数千万レコードのテーブルということですが、SNSはすごいデータ量なんですね。

さらに、ソートというのはインデックスの意味がないため、これだけのレコード数になると非常にボトルネックになるようです。
(これはSQL Server2005の実行プランという面白い機能でも確認済みです。ただ単にソートするだけでも80%近くのコストがかかってます)

これらの対策として、GREEではアクセスがきてSQLを発行しデータ取得するのではなく、あらかじめデータが更新された時点で表示するためのページの部品を構築しておくという手法つまり、「フックを利用したイベント通知機構」とものらしいです。
ざっとしか見てないので、実装面は深く理解できてませんが、なかなかユニークなアプローチだと思いました。

確かにレスポンスを早くするための工夫は技術者としての力が求められる部分です。
この分野での力をつけていかないとプログラマとしての人生も短いなと実感しました。

余談ですが、今作ってるプロジェクトもSNSのマイページ的なものがあって新着情報をいろいろ出すのですが、いかんせんいくつものテーブルを見て結合しているため非常に表示が遅いです。(しかもまだデータが数百件レベルで。。)
仕方なしにNowLoadingとかいう画面を一枚はさんでる状態です。
まあ納期の問題とか担当が違うって点もあるんですが。。。
[PR]
by jehoshaphat | 2008-09-11 16:36 | 思ったこととかニュースとか。。 | Trackback | Comments(0)
(.Net)画像ファイルを表示しながら削除可能にする方法
PictureBoxであるイメージファイルを表示したままそのファイルを消す場合の方法です。
通常ファイル名を指定して Bitmap オブジェクトを作成し、Pictureboxにセットした後、File.Delete(パス) で消しますが、こうすると例外発生します。
なぜなら Bitmap をファイルから作成した場合、その Bitmap オブジェクトが解放されるまでイメージファイルをロックするからです。

ということで、下記のコードでは読み込み専用のオブジェクトを使って読み込み、Picturebox表示用イメージを作成後、読み込み専用オブジェクトを破棄(Discope)します。
破棄した時点でファイル操作(削除とか)が可能になります。

Imports System.IO
 
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Try
'読み込みだけに使う一時イメージオブジェクト(読み込み専用オブジェクト)
Dim bufBmp As New Bitmap("C:\test.jpg")
'Pictureboxに表示するイメージオブジェクト作成
Dim bmp As New Bitmap(bufBmp)
'読み込み一時用イメージオブジェクト解放(解放した時点でファイルのロックが解放される)
bufBmp.Dispose()
Me.PictureBox1.Image = bmp
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
 
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Try
File.Delete("C:\test.jpg")
Catch ex As Exception
MsgBox(ex.Message)
 
End Try
End Sub
End Class

[PR]
by jehoshaphat | 2008-09-09 15:05 | .Net開発 | Trackback | Comments(0)
(VS2005) ある条件になったらブレークさせる方法
デバッグ時にブレークポイントを張ってそこからステップインでデバッグというのは、IDE使ってる開発者なら誰もがやってる思います。
このとき、ある条件を満たせばブレークしたいという時も結構あるのではないでしょうか。
ViisualStudio2005にはその機能が用意されています。
が、自身も気がついたのはごく最近で、周りでも有効に使ってる人はいませんでした。

方法はごくごく簡単で、ブレークポイントを張ったのち、そのブレークポイントを右クリックして、「条件」を押下します。
「ブレークポイントの条件」という子ウィンドウが出るので、そこで条件式を入れます。
(C#の場合は比較演算子は if 文で用いる時と同じように == と書かないといけません。VBの場合は = でOK見たいです。)
「trueの場合」にチェックを入れると、条件式で得られる値がtrueのときにデバッグがブレークします。
「変更された場合」にチェックを入れると、条件式で得られる値が変更されたときにデバッグがブレークします。
e0091163_10353245.jpg


条件が付いたブレークポイントはアイコンの中に白十字がでて分かりやすくなってます。
e0091163_10355122.jpg


他にも、VSのブレークポイントはヒットカウントとかフィルタとかあるので、使いこなせればかなりデバッグに活用できますね。

参考:
@IT特定の条件のときにデバッグをブレーク(停止)させるには?[C#、VB]
Visual Studioでブレークポイントを設定(条件付き)
[PR]
by jehoshaphat | 2008-09-05 10:39 | .Net開発 | Trackback | Comments(0)
(VB.Net).NetからのPDFファイル印刷方法
.Netで作ったプログラムからPDFファイルを印刷する方法です。
なお、.Net自体はPDFを理解できないので、AcrobatかAdobeReaderプロセスを起動させて印刷させる方法です。
(これ以外に方法があったら教えてください。)
ということで、AcrobatかAdobeReaderがインストールされていない環境では使えません。



'====レジストリからAcrobat,AcrobatReaderのパス取得====
Dim strRegPath As String
Dim rKey As RegistryKey
'キーを取得(最初にAcrobat,だめならAdobeReader)
strRegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\Acrobat.exe"
rKey = Registry.LocalMachine.OpenSubKey(strRegPath)
If rKey Is Nothing Then
strRegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\AcroRd32.exe"
rKey = Registry.LocalMachine.OpenSubKey(strRegPath)
End If
'値(exeのパス)を取得(既定の値の場合は空文字指定)
Dim location As String
Try
'値(exeのパス)を取得(既定の値の場合は空文字指定)
location = DirectCast(rKey.GetValue(""), String)
Catch ex As NullReferenceException
Throw New ApplicationException("AcrobatもしくはAdobeReaderがインストールされていないため、PDFファイルの印刷ができません。")
Finally
'開いたレジストリキーを閉じる
rKey.Close()
End Try
 
'===Acrobatを起動し印刷===
Dim filepath As String = "D:\print_test.pdf"
Dim pro As New Process()

'.Net的書き方(C#でも可能な書き方)
'Acrobatのフルパス設定
pro.StartInfo.FileName = location
pro.StartInfo.Verb = "open"
'Acrobatのコマンドライン引数設定
pro.StartInfo.Arguments = " /n /t " + filepath
pro.StartInfo.WindowStyle = ProcessWindowStyle.Hidden
'プロセスを新しいWindowで起動
pro.StartInfo.CreateNoWindow = True
'プロセス起動
pro.Start()
'プロセス終了
pro.WaitForExit(5000)
pro.Kill()
 
 
'VB的書き方
'Dim procID As Integer
'procID = Shell(location & " /n /t " & filepath)
'pro = Process.GetProcessById(procID)
'pro.WaitForExit(3000)
'pro.Kill()


このソース(特に.Net的書き方)は@ITで上がってた掲示板を参考にさせてもらってます。

まず、レジストリからAcrobat,AdobeReaderのexeのパスを取得します。
レジストリのどこにあるかはAdobeのサポートページに書かれていました。

あとはexeに印刷用引数を渡して起動させるだけです。
/t というのがAdobe Reader を起動し、印刷ダイアログボックスを表示せずにファイルを印刷する引数みたいです。
/n はAdobe Reader のインスタンスが現在開いていても、別のインスタンスを起動するという意味みたいです。
引数については下記のページを参考にさせてもらいました。
AcroRd32.exeのコマンドプロンプトからの引数
Adobe Reader 8.1の起動オプション(その2)


追記:PDFファイルを.Net上で読み込ませるには"】iText.NET"というOSSライブラリが利用できるみたいです。

再追記:この方法だと、終了処理に問題があります。詳しくは(VB.Net)[補足].NetからのPDFファイル印刷方法を参照してください。
[PR]
by jehoshaphat | 2008-09-05 09:51 | .Net開発 | Trackback | Comments(0)
MSのボリュームライセンス
ボリュームライセンスについてはよく耳にしますが、実際どうなってるのといわれるとなかなか難しいものです。
特にMSのボリュームライセンスにはOpen ValueやOpen Licenceなどいくつか種類がそれらの違いもなかなかつかめません。

そのややこしいMSのボリュームライセンスについて、下記のページに分かりやすい解説が出ていました。
ボリュームライセンスを知るとマイクロソフト製品が安くなる?・第一回
ボリュームライセンスを知るとマイクロソフト製品が安くなる?・第二回
ボリュームライセンスを知るとマイクロソフト製品が安くなる?・最終回


詳しい解説は上記のページに任せるとして個人的に納得した部分です。

よく ライセンス(L)と ソフトウェアアシュアランス(SA)というのを耳にします。
よーやくこれらの意味がパッとわかるようになりました。
L:その製品の無期限使用権(パッケージ購入のようなもの)
SA:その製品の保守的な権利のようなもので、さまざまな特典(一番はアップグレード権)が付く。

SAは契約期間が決まってるので、延長したい場合は延長契約が必要みたいです。
また、契約期間も各ボリュームライセンスの種類によって異なるようです。

最終回では実際にOffice2007とWindowsServer2003の購入において、パッケージ、Open Business、Open Valueの比較がなされています。
面白いのは、Officeで5年おきにバージョンアップする場合は、パッケージ購入のほうがボリュームライセンスより安いという点です。
しかし、WindowsServerのほうはやはりボリュームライセンスを適用したほうが安いようです。

ボリュームライセンスでも、Open BusinessとOpen Valueではバージョンアップの期間によって金額が大きく異なります。

結局、製品の導入サイクルポリシーを決めて、それにそった一番お得な購入方法を選択するということが必要だということですね。
[PR]
by jehoshaphat | 2008-09-01 16:30 | 豆知識 | Trackback | Comments(0)