I am trying to decompile over 30k vulkan shader files using shaderc from google.
All shaders are located in "C:\Users\Admin\Desktop\NMS MOD\SHADER MOD\v2.41\PC"
The tool used to decompile is spirv-cross.exe which I added to Windows Environment variables, which lets me run this simple bat file inside the shaders folder and works fine.
"spirv-cross --version 450 --vulkan-semantics --stage frag ATMOSPHERE_FRAG_CLOUD_769.SPV > ATMOSPHERE_FRAG_CLOUD_769.GLSL"
Since there is way too many to do this manually. I want to make a simple App to do this process and also get the stage type from file name (in this case "frag").
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
namespace Lazy_Me_3
{
public partial class Form1 : Form
{
public string PATH;
public string[] sFilesNames;
public int totalcount = 0;
public int currentcount = 0;
public Form1()
{
InitializeComponent();
}
private string GetStageType(string filename)
{
// Valid Stages = vertex, vert, fragment, frag, tesscontrol, tesc, tesseval, tese, geometry, geom, compute, comp
if (filename.Contains("_VERTEX_") || filename.Contains("_VERT_")) return "vert";
if (filename.Contains("_FRAGMENT_") || filename.Contains("_FRAG_")) return "frag";
if (filename.Contains("_TESSCONTROL_") || filename.Contains("_TESC_")) return "tesc";
if (filename.Contains("_TESSEVEL_") || filename.Contains("_TESE_")) return "tese";
if (filename.Contains("_GEOMETRY_") || filename.Contains("_GEOM_")) return "geom";
if (filename.Contains("_COMPUTE_") || filename.Contains("_COMP_")) return "comp";
else return "error";
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < sFilesNames.Count(); i++)
{
sFilesNames[i] = Path.GetFileName(sFilesNames[i]);
if (sFilesNames[i].Length > 1)
{
var newName = sFilesNames[i].Substring(0, sFilesNames[i].Length - 4);
sFilesNames[i] = newName;
}
}
foreach (var file in sFilesNames)
{
string stageType = GetStageType(file);
if (stageType != "error")
{
string args = "--version 450 --vulkan-semantics --stage " + stageType + " " + file + ".SPV" + " > " + file + ".GLSL";
Process process = new Process();
process.StartInfo.FileName = "spirv-cross";
process.StartInfo.Arguments = args;
process.StartInfo.WorkingDirectory = PATH;
process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
process.Start();
process.WaitForExit(5000);
currentcount += 1;
label1.Text = "Status : " + currentcount.ToString() + " / " + totalcount.ToString();
}
else MessageBox.Show("Error on finding stage type of file : " + file);
}
}
private void button2_Click(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
DialogResult result = fbd.ShowDialog();
if (result == DialogResult.OK && !string.IsNullOrWhiteSpace(fbd.SelectedPath))
{
sFilesNames = Directory.GetFiles(fbd.SelectedPath, "*.SPV");
totalcount = sFilesNames.Length;
PATH = fbd.SelectedPath;
label3.Text = "Directory : " + PATH;
label2.Text = "Total Count : " + totalcount.ToString();
label1.Text = "Status : 0 / " + totalcount.ToString();
button1.Enabled = true;
}
}
}
}
}
EDIT 1 : Bodge using cmd that works
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < sFilesNames.Count(); i++)
{
//sFilesNames[i] = Path.GetFileName(sFilesNames[i]);
if (sFilesNames[i].Length > 1)
{
var newName = sFilesNames[i].Substring(0, sFilesNames[i].Length - 4);
sFilesNames[i] = newName;
}
}
foreach (var file in sFilesNames)
{
string stageType = GetStageType(file);
if (stageType != "error")
{
var p = new ProcessStartInfo("cmd", #"/c spirv-cross --version 450 --vulkan-semantics --stage " + stageType + " " + file + ".SPV" + " > " + file + ".GLSL");
p.UseShellExecute = false;
p.CreateNoWindow = true;
var ps = Process.Start(p);
ps.WaitForExit();
currentcount += 1;
label1.Text = "Status : " + currentcount.ToString() + " / " + totalcount.ToString();
}
else
{
errorcount += 1;
label4.Text = "Errors : " + errorcount.ToString();
}
}
}
Related
I am running multiple instances of an application that reads first line from a file, then it deletes the first line and saves the file under the same name. I found out that in some instances the applications will crash. I created a sample program just to better understand the issues I have.
If I run four instances of this program, sometimes multiple instances attempt to delete the same line. In the end the operation succeeds, but it is not efficient. How can I improve the code to avoid this? Perhaps each instance needs to lock the file while it uses it.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
using System.Threading;
using System.Diagnostics;
namespace ConcurrentFileAccess
{
public partial class MainForm : Form
{
bool gbAbort = false;
public MainForm()
{
InitializeComponent();
}
void BtnCreateFileClick(object sender, EventArgs e)
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
Stopwatch stopwatch = Stopwatch.StartNew();
if (File.Exists(sFile)) {
File.Delete(sFile);
}
if (!File.Exists(sFile)) {
List<string> list = new List<string>();
var fc = File.Create(sFile);
fc.Close();
for (int i = 1; i <= 200; i++) {
list.Add(i.ToString());
}
File.WriteAllLines(sFile, list);
listBox1.Items.Add("File " + sFile + " was created and it contains 200 lines");
} else {
string[] lines = File.ReadAllLines(sFile);
int nlines = lines.Length;
listBox1.Items.Add("File " + sFile + " already exists and it contains " + nlines + " lines");
}
stopwatch.Stop();
listBox1.Items.Add("File created in " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
}
void BtnDeleteFromFileClick(object sender, EventArgs e)
{
gbAbort = false;
int nlines = 9999;
while (nlines > 0) {
nlines = DeleteOneLine();
Application.DoEvents();
if (gbAbort) {
return;
}
}
}
int DeleteOneLine()
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
listBox1.Items.Add("We are in DeleteLines()...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
int nLinesLeft = 9999;
string line0 = string.Empty;
Stopwatch stopwatch = Stopwatch.StartNew();
int ntry = 0;
while (ntry < 100) {
try {
string[] lines = File.ReadAllLines(sFile);
List<string> list = new List<string>(lines);
nLinesLeft = list.Count;
if (nLinesLeft > 0) {
line0 = list[0];
list.RemoveAt(0);
listBox1.Items.Add("Deleted line " + line0);
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
listBox1.Items.Add("Writing to file after line " + line0 + " was deleted");
File.WriteAllLines(sFile, list);
nLinesLeft = list.Count;
Application.DoEvents();
} else {
nLinesLeft = 0;
break;
}
} catch (Exception) {
ntry++;
listBox1.Items.Add("ntry = " + ntry + ", could not delete line " + line0 + " from file. Attempting again...");
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
Application.DoEvents();
Thread.Sleep(50);
}
}
if(ntry >= 100) {
nLinesLeft = -1; // should never get here
}
stopwatch.Stop();
listBox1.Items.Add("ntry: " + ntry + ", lines Left: " + nLinesLeft + ", elapsed = " + stopwatch.Elapsed.ToString("hh\\:mm\\:ss\\.fff"));
listBox1.SelectedIndex = listBox1.Items.Count - 1;
Application.DoEvents();
return nLinesLeft;
}
void BtnAbortClick(object sender, EventArgs e)
{
gbAbort = true;
}
void BtnOpenAppFolderClick(object sender, EventArgs e)
{
string sFile = Application.ExecutablePath;
string sPath = Path.GetDirectoryName(sFile);
Process.Start(sPath);
}
void BtnOpenFileClick(object sender, EventArgs e)
{
string sFile = #"S:\Temp\concurrentFileAccess.txt";
if(File.Exists(sFile)) {
Process.Start(sFile);
}
else {
MessageBox.Show("File " + sFile + " not found");
}
}
}
}
I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response
Backgroundworker dowork event
string CurrentFileWithPath;
private void _FileProcessingWorker_DoWork(object sender, DoWorkEventArgs e)
{
try
{
DirectoryInfo[] MySubDirectories = (DirectoryInfo[])e.Argument;
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
{
DirectoryInfo MySubDirectory = MySubDirectories[i];
List<FileInfo> l = new List<FileInfo>();
CountFiles(MySubDirectory, l);
int totalFiles = l.Count;
object[] CurrentStatus = new object[5];
CurrentStatus[3] = i.ToString();
CurrentStatus[4] = totalFiles.ToString();
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
string CurrentDirectory = "Current Directory: " + MySubDirectory.Name;
foreach (FileInfo MyFile in l)
{
CurrentStatus = new object[5];
if (_FileProcessingWorker.CancellationPending)
{
e.Cancel = true;
return;
}
if (MyFile.Extension.ToLower() == ".cs" || MyFile.Extension.ToLower() == ".vb")
{
string CurrentFile = "Current File: " + MyFile.Name;
string CurrentFileWithPath = MyFile.FullName;
CurrentStatus[0] = CurrentDirectory;
CurrentStatus[1] = CurrentFile;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
List<string> Result = SearchInFile(CurrentFileWithPath, "static class FileShellExtension");
if (Result != null && Result.Count > 0)
{
CurrentStatus[2] = Result;
_FileProcessingWorker.ReportProgress(0, CurrentStatus);
}
}
}
}
}
catch (Exception err)
{
return;
}
Progresschanged event
private void _FileProcessingWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (typeof(object[]) == e.UserState.GetType())
{
object[] StatusMsg = (object[])e.UserState;
if (5 == StatusMsg.GetLength(0))
{
label2.Text = StatusMsg[4].ToString();
label4.Text = StatusMsg[3].ToString();
if (StatusMsg[0] != null && StatusMsg[1] != null)
{
lblCurrentDirectory.Text = StatusMsg[0].ToString();
lblStatus.Text = StatusMsg[1].ToString();
}
if (StatusMsg[2] != null)
{
if (StatusMsg[2].GetType() == typeof(List<string>))
{
List<string> l = (List<string>)StatusMsg[2];
for (int i = 0; i < l.Count; i++)
{
ListViewCostumControl.lvnf.Items.Add("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
w.WriteLine("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
}
}
}
}
}
}
CountFiles method
private void CountFiles(DirectoryInfo di, List<FileInfo> l)
{
try
{
l.AddRange(di.EnumerateFiles());
}
catch
{
string fff = "";
}
try
{
IEnumerable<DirectoryInfo> subDirs = di.EnumerateDirectories();
if (subDirs.Count() > 0)
{
foreach (DirectoryInfo dir in subDirs)
CountFiles(dir, l);
}
}
catch
{
string yyy = "";
}
}
SearchInFile method
private List<string> SearchInFile(string fileToSearch, string textToSearch)
{
List<string> l = new List<string>();
try
{
foreach (var line in File.ReadAllLines(fileToSearch))
{
if (line.Contains(textToSearch))
l.Add(line);
}
}
catch(Exception err)
{
string fff = err.ToString();
}
return l;
}
The first problem is when getting the number of directories:
private void btnProcess_Click(object sender, EventArgs e)
{
btnProcess.Enabled = false;
btnDirectory.Enabled = false;
btnCancel.Visible = true;
btnCancel.Enabled = true;
btnCancel.Text = "Cancel";
MyProgressBar.Visible = true;
_FileProcessingWorker = new BackgroundWorker();
_FileProcessingWorker.WorkerReportsProgress = true;
_FileProcessingWorker.WorkerSupportsCancellation = true;
_FileProcessingWorker.DoWork += new DoWorkEventHandler(_FileProcessingWorker_DoWork);
_FileProcessingWorker.ProgressChanged += new ProgressChangedEventHandler(_FileProcessingWorker_ProgressChanged);
_FileProcessingWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_FileProcessingWorker_RunWorkerCompleted);
string BasePath = lblDirectoryName.Text;
DirectoryInfo MyDirectory = new DirectoryInfo(BasePath);
DirectoryInfo[] MySubDirectories = MyDirectory.GetDirectories();
int SubDirectoryCount = MySubDirectories.GetLength(0);
MyProgressBar.Minimum = 0;
MyProgressBar.Step = 1;
MyProgressBar.Maximum = SubDirectoryCount;
MyProgressBar.Value = MyProgressBar.Minimum;
_LastCounter = 0;
_FileProcessingWorker.RunWorkerAsync(MySubDirectories);
}
In the click button i'm getting the sub directories.
But there are two problems.
In the dowork event when i put a break point on this line:
for (int i = 0; i < MySubDirectories.GetLength(0); i++)
I see that it contain 409 directories. But when i report the number of directories to the label4 in the dowork event
CurrentStatus[3] = i.ToString();
In the progresschanged event
label4.Text = StatusMsg[3].ToString();
I see in the end on label4 408 directories. And in D:(in this case i'm working on my D:\ directory) when i select all the directories in windows explorer make right click and properties i see only 405 directories. So what is the real number of directories ? What and how number of directories should i display in label4 ?
The second problem is when i report the number of files in dowork event:
CurrentStatus[4] = totalFiles.ToString();
And in progresschanged event show it on label2:
label2.Text = StatusMsg[4].ToString();
The problem is that the totalFiles value is changing all the time once it's 2 then it's 768 then it's 66 then 8987 but what i want to do is somehow to sum in real time the values in totalFiles so in label2 i will see first time for example: 2 then 770 then (770+66) so i will see in label2 816....to see always the sum of all the values so far.
The last problem is in the progresschanged event this loop:
for (int i = 0; i < l.Count; i++)
{ ListViewCostumControl.lvnf.Items.Add("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
w.WriteLine("Directory: " + lblCurrentDirectory.Text + "In File: " + lblStatus.Text + l[i]);
}
It might be logic somehow to take out and make this loop at this time in the program in another backgroundworker like backgroundworker2 dowork event ? If so how to do it ? The problem is when the loop have many items to add to the listView it make the program to hang until the loop finish.
Each time you execute
CurrentStatus[4] = totalFiles.ToString();
You are resetting the status value to the count of files in the current processing directory. This is why the number keeps bouncing around. Instead I would suggest:
int thisDirFiles;
thisDirFiles = l.Count;
totalFiles += thisDirFiles;
CurrentStatus[4] = totalFiles.ToString();
Now when you report progress, CurrentStatus[4] will have the running total.
For your second question, it looks to me you are trying to do too much when you are reporting progress. Manipulating ListViews can be costly, and you are probably spending more time updating the ListView than you are processing the directories, so your machine seems to freeze.
I have a DotNetZip code for zipping the folder. It doesnt zip the file for the first time after cleaning the solution. After that it works fine. Can anybody know the issue why its happening??
Button Click Event Code
private void button3_Click(object sender, EventArgs e)
{
try
{
copy_stuff(textBox1.Text, textBox2.Text, textBox3.Text);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Method that gets called from Button Click
private void copy_stuff(string srcFolder, string destFolder, string Backup)
{
using (ZipFile zip = new ZipFile())
{
zip.AddProgress += AddProgressHandler;
zip.CompressionLevel = Ionic.Zlib.CompressionLevel.Default;
zip.SaveProgress += SaveProgress;
zip.StatusMessageTextWriter = System.Console.Out;
zip.AddDirectory(destFolder);
zip.Save(Backup + "\\VibrantBackup" + DateTime.Now.ToString("yyyyMMdd hh.mm.ss") + ".zip");
label1.Text = "Compression completed.";
}
}
Add & Save Handlers for Progress
int _numEntriesToAdd = 0;
int _numEntriesAdded = 0;
void AddProgressHandler(object sender, AddProgressEventArgs e)
{
switch (e.EventType)
{
case ZipProgressEventType.Adding_Started:
_numEntriesToAdd = 0;
_numEntriesAdded = 0;
label1.Text = "Adding files to the zip...";
label1.Update();
Application.DoEvents();
break;
case ZipProgressEventType.Adding_AfterAddEntry:
_numEntriesAdded++;
label1.Text = String.Format("Adding file: {0} :: {2}",
_numEntriesAdded, _numEntriesToAdd, e.CurrentEntry.FileName);
label1.Update();
Application.DoEvents();
break;
case ZipProgressEventType.Adding_Completed:
label1.Text = "Added all files";
label1.Update();
Application.DoEvents();
break;
}
}
public void SaveProgress(object sender, SaveProgressEventArgs e)
{
if (e.EventType == ZipProgressEventType.Saving_Started)
{
label1.Text = "Begin Saving: " + e.ArchiveName;
label1.Update();
Application.DoEvents();
}
else if (e.EventType == ZipProgressEventType.Saving_BeforeWriteEntry)
{
label1.Text = "Processing : " + e.CurrentEntry.FileName;
label1.Update();
label3.Text = "Files Processed: (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
label3.Update();
Application.DoEvents();
progressBar3.Maximum = e.EntriesTotal;
progressBar3.Value = e.EntriesSaved + 1;
}
else if (e.EventType == ZipProgressEventType.Saving_EntryBytesRead)
{
//progressBar2.Value = (int)((e.BytesTransferred * 100) / e.TotalBytesToTransfer);
//label3.Text = "Writing: " + e.CurrentEntry.FileName + " (" + (e.EntriesSaved + 1) + "/" + e.EntriesTotal + ")";
label1.Update();
Application.DoEvents();
}
}
Before coming to SO for an answer I've spent the last 2 or 3 days on Google trying different question forms to try and get this to work.
I need to get the color setting of the current print job to determine how many color or grayscale prints a user has performed. However every single color property I've tried to access (through ManagementObjectSearcher, ""Watcher, and the built-in printer classes of C#) always return color, never grayscale.
Any help would be greatly appreciated, since I've come to a stop on making progress with solutions. Thanks. Below is the code I have (keep in mind it's my prototyping code so there might be many issues apart from what I'm asking. Please only provide suggestions WITH your answer to my question).
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Printing;
using System.Management;
using System.Management.Instrumentation;
using System.Threading;
using System.Windows.Threading;
using System.Diagnostics;
namespace PrintPlus {
public partial class PrintPlus : Form {
#region Objects
// Mgmt
ManagementEventWatcher watcher;
ManagementObjectSearcher searcher;
// Thread
Thread jobCheck;
// Printer Objects
PrintQueue printQ;
PrintJobInfoCollection printJobCollection;
// Timer
private System.Windows.Forms.Timer timeLogged;
#endregion
#region Paths And Names
string localMachineName;
#endregion
#region Costs
private decimal timeCost;
private decimal printCost;
#endregion
#region Print Variables
private int color;
private bool jobIsProcessing;
private int numberOfPrints;
private int colorPrints;
private int greyScalePrints;
private int printJobCount;
#endregion
#region Time Variables
private float tSecs;
private float tMins;
private float tHrs;
#endregion
#region Constructor
public PrintPlus() {
InitializeComponent();
initObjects();
/* searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PrintJob");
watcher = new ManagementEventWatcher("SELECT * FROM __InstanceCreationEvent WITHIN 0.01 WHERE TargetInstance ISA \"Win32_PrintJob\"");
watcher.EventArrived += new EventArrivedEventHandler(getColorSetting);
watcher.Start();
localMachineName = Environment.MachineName;*/
}
#endregion
#region Initializers
private void initObjects() {
initPrinterObjects();
initTimer();
}
private void initPrinterObjects() {
LocalPrintServer lps = new LocalPrintServer();
printQ = new PrintQueue(lps, lps.DefaultPrintQueue.Name);
}
private void initTimer() {
timeLogged = new System.Windows.Forms.Timer();
timeLogged.Interval = 1000;
timeLogged.Tick += new EventHandler(onTick);
timeLogged.Start();
}
#endregion
#region Delegates
private void onTick(object sender, EventArgs e) {
updateTime();
updateInfo();
}
private void onMove(object sender, EventArgs e) {
this.Location = initialPosition;
}
private void onLoseFocus(object sender, EventArgs e) {
this.MinimizeBox = true;
}
#endregion
#region Updates
private void updateInfo() {
printJobCount = printQ.GetPrintJobInfoCollection().Count<PrintSystemJobInfo>();
if (printJobCount >= 1 && !jobIsProcessing) {
jobIsProcessing = true;
jobCheck = new Thread(new ThreadStart(processJobs));
jobCheck.Start();
}
numberOfPrints = (colorPrints + greyScalePrints);
timeCostLbl.Text = "Time: $" + timeCost.ToString();
printCostLbl.Text = "Print: $" + printCost.ToString();
totalCostLbl.Text = "Total: $" + (timeCost + printCost).ToString();
printedPagesLbl.Text = "Printed Pages: " + numberOfPrints.ToString() + " Colour: " + colorPrints.ToString() + " B&W: " + greyScalePrints.ToString();
}
private void updateTime() {
tSecs += timeLogged.Interval / 1000;
if (tSecs == 60) {
timeCost += FEES.COST_PER_MIN;
tMins += 1;
if (tMins == 60) {
tHrs += 1;
}
tSecs = 0;
}
int i = 0;
String hrs = ((tHrs >= 10) ? tHrs.ToString() : i + tHrs.ToString());
String mins = ((tMins >= 10) ? tMins.ToString() : i + tMins.ToString());
String secs = ((tSecs >= 10) ? tSecs.ToString() : i + tSecs.ToString());
this.timeElapsedLbl.Text = "Time Logged: " + hrs + " : " + mins + " : " + secs;
}
public void processJobs() {
LocalPrintServer lps = new LocalPrintServer();
PrintQueue printQ = new PrintQueue(lps, lps.DefaultPrintQueue.Name);
PrintJobInfoCollection printJobCollection = printQ.GetPrintJobInfoCollection();
PrintSystemJobInfo[] jobArray = printJobCollection.ToArray<PrintSystemJobInfo>();
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PrintJob");
ManagementObjectCollection searchCollection = searcher.Get();
foreach (ManagementObject job in searchCollection) {
foreach (PropertyData prop in job.Properties) {
Debug.WriteLine(prop.Name + ": " + prop.Value);
}
}
try {
for (int i = 0; i < jobArray.Length; ++i) {
if (jobArray[i].PositionInPrintQueue == 1) {
while (jobArray[i].JobStatus != PrintJobStatus.Deleted) {
jobArray[i].Refresh();
}
}
Debug.WriteLine(printQ.CurrentJobSettings.CurrentPrintTicket.OutputColor.Value);
/*if (jobArray[i].PropertiesCollection. == "Color") {
colorPrints += jobArray[i].NumberOfPagesPrinted;
}
else if (jobArray[i].PropertiesCollection["Color"].ToString() == "Monochrome") {
greyScalePrints += jobArray[i].NumberOfPagesPrinted;
}*/
}
}
finally {
jobIsProcessing = false;
lps.Dispose();
printQ.Dispose();
printJobCollection.Dispose();
jobCheck.Abort();
}
}
private void getPrintWatcher(int jobID) {
}
private void getColorSetting(object sender, EventArrivedEventArgs e) {
/* foreach (PropertyData data in e.NewEvent.Properties) {
ManagementBaseObject mbo = data.Value as ManagementBaseObject;
if (mbo.Properties["Color"].Value == "Color") {
color = COLOR_VALUES.COLOR;
}
else if (mbo.Properties["Color"].Value == "Monochrome") {
color = COLOR_VALUES.MONO;
}
}*/
}
#endregion
}
}
I believe the problem you are experiencing is because the printer is capable of printing in color and black and white. When you print a black letter text document via a color printer the WIN32_PrintJob will still say that the document is a color document UNLESS you explicitly tell the printer to print in black and white via the local machine's 'printer preferences' dialog.
Color counter of each printer maker and model works differently. Your best bet would be before processing the printing, go through the printing material and determine the colour pages and black pages. If not you will have to relay on the machine counter which only available for Multi functional printers, you can get this information through SNMP.
I spent a lot of time to weigh out how to get the real value of the defined color printing and discovered that Win32_PrintJob provides this information in this way:
public static bool PausePrintJob(string printerName, int printJobID)
{
bool isActionPerformed = false;
string searchQuery = "SELECT * FROM Win32_PrintJob";
ManagementObjectSearcher searchPrintJobs = new ManagementObjectSearcher(searchQuery);
ManagementObjectCollection prntJobCollection = searchPrintJobs.Get();
foreach (ManagementObject prntJob in prntJobCollection)
{
System.String jobName = prntJob.Properties["Name"].Value.ToString();
//Job name would be of the format [Printer name], [Job ID]
char[] splitArr = new char[1];
splitArr[0] = Convert.ToChar(",");
string prnterName = jobName.Split(splitArr)[0];
int prntJobID = Convert.ToInt32(jobName.Split(splitArr)[1]);
string documentName = prntJob.Properties["Document"].Value.ToString();
if (String.Compare(prnterName, printerName, true) == 0)
{
if (prntJobID == printJobID)
{
// MessageBox.Show("PAGINAS : " + prntJob.Properties["TotalPages"].Value.ToString() + documentName + " " + prntJobID);
prntJob.InvokeMethod("Pause", null);
MessageBox.Show(prntJob.Properties["Color"].Value.ToString());
//prntJob.InvokeMethod("Resume", null);
isActionPerformed = true;
break;
}
}
}
return isActionPerformed;
}