I want to read from and write to a file in C# - c#

here is my code without files
static void Main(string[] args)
{
// BluetoothRadio.PrimaryRadio.Mode = RadioMode.Connectable;
BluetoothClient bc = new BluetoothClient();
BluetoothDeviceInfo[] devs = bc.DiscoverDevicesInRange();
foreach (BluetoothDeviceInfo d in devs)
{
System.Console.WriteLine(d.DeviceName);
}
System.Console.WriteLine("finish");
System.Console.ReadLine();
}
Instead of the line System.Console.WriteLine(d.DeviceName);
I want that part to be written into a file.
After that I need to loop on that file, and for each device name in that file, I will search in another file for it's corresponding output. A hint on how to loop on and search in files will be sufficient for that part.
Thank you.

You can use File.AppendAllText() as an exact drop-in (but you'll need to append Environment.NewLine to your text).
Make sure that you delete the file if it exists before your foreach loop, possibly prompting the user for confirmation depending on your requirements.

Related

Trouble with transfer function in WIA C#

I have a problem with the below code. I want to scan a document by clicking a button in a WinForms C# application.
I use WIA, Visual studio and the scanner Fujitsu N7100A working with Windows 8. I am following a tutorial online for using WIA.
But the program doesn't run as expected. It seems to break down at the Transfer method.
// Create a DeviceManager instance
var deviceManager = new DeviceManager();
// Create an empty variable to store the scanner instance
DeviceInfo firstScannerAvailable = null;
// Loop through the list of devices to choose the first available
AddLogs(deviceManager.DeviceInfos.Count.ToString(), filename);
foreach (DeviceInfo d in deviceManager.DeviceInfos)
{
if (d.Type == WiaDeviceType.ScannerDeviceType)
{
firstScannerAvailable = d;
}
}
// Connect to the first available scanner
var device = firstScannerAvailable.Connect();
// Select the scanner
var scannerItem = device.Items[0];
// Retrieve a image in JPEG format and store it into a variable
var imageFile = (ImageFile)scannerItem.Transfer(FormatID.wiaFormatPNG);
//Save the image in some path with filename
var path = #"C:\Documents\scan.png";
if (File.Exists(path))
{
File.Delete(path);
}
// Save image !
imageFile.SaveFile(path);
I just have to remove the addition of lines in the file of log.
This is much more of a workaround since i have no idea about your scanner.
I would assume that all scanners has a drive where they store their scanned documents, like mine, So i would suggest that you read all available drives loop through them check for DriveType and VolumeLabel and then read it's files and copy the document where you want
Something like this :
foreach (var item in DriveInfo.GetDrives())
{
//VolumeLabel differs from a scanner to another
if (item.VolumeLabel == "Photo scan" && item.DriveType == DriveType.Removable)
{
foreach (var obj in Directory.GetFiles(item.Name))
{
File.Copy(obj, "[YOUR NEW PATH]");
break;
}
break;
}
}
Finaly a TWAIN application work with this scanner. I will work with that. I don't said why do that work with TWAIN and not with WIA but that the reality. Sorry for this waste of time. Thank you for the answers. Have a nice day.
I am currently solving this very problem. It seems the N7100A driver sets the Pages property of the device to 0, which should mean continous scanning, but the transfer method is unable to handle this value. You must set that property to 1:
var pages = 1;
// Not all devices have this property, but Fujitsu N7100A has.
device.Properties["Pages"]?.set_Value(ref pages);
I think the problem is here
var scannerItem = device.Items[0];
as WIA indexes are NOT zero based so it should be 1 instead
var scannerItem = device.Items[1];

C# PrintQueue AddJob printingHandle throws null exception

I'm trying to print a file with C#. I have made some headway in listing off all the printers and then wrote some simple logic to select the correct printer:
var server = new PrintServer();
var queues = server.GetPrintQueues(new[] { EnumeratedPrintQueueTypes.Local, EnumeratedPrintQueueTypes.Connections }).ToList();
int count = 0;
foreach (var q in queues)
{
Console.WriteLine(count++ + " " + q.Name);
}
int iSelection = 0;
while (true)
{
Console.Write("Select printer: ");
string selection = Console.ReadLine();
if (int.TryParse(selection, out iSelection) && iSelection >= 0 && iSelection < queues.Count())
{
break;
}
else
{
Console.WriteLine("Bad selection, try again.");
}
}
The next step, as for the posts I've seen on this site, is that you need to select the specific queue, and then add a job, grab the job stream, and write to the stream (at least that's how I want to try to do it, unless it's wrong?)
var queue = queues[iSelection];
var job = queue.AddJob(#".\Test.txt");
var stream = job.JobStream;
var file = File.ReadBytes(#".\Test.txt");
stream.Write(file, 0, file.Length);
When I do this, the program crashes at the line with AddJob. Specifically,
System.ArgumentNullException: 'Value cannot be null, Parameter name: printingHandler'
Now, I think I understand what the issue is. I had been playing with System.Drawing.Printing.PrintDocument yesterday, but I am trying to find a solution that allows me to print files, rather than manually draw them out and them print them. Ultimately, the goal in the future is to be able to print out text and PDF files (I was hoping that this solution would allow me to open a PDF file and dump the bytes into this stream, but I don't know if that's the correct way to this?)
Anyway, the exception I got I think is something similar to PrintDocument's PrintPageEventHandler, I need to add a callback to the PrintQueue somehow that tells it the font, color, font size, etc. Problem is that I see nothing for PrintQueue that allows me to add a handle for it to fix this issue.
What can I do to fix this exception?
I was having this issue as well. Eventually I found out that we need to call into Refresh() of the selected PrintQueue instance and before calling AddJob().

Move directory on system when executed C#? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I'm looking to move my C# application .EXE when ran to lets say... Documents and then delete from the place which it was executed.
For example, If I ran my .EXE on my desktop before running the program copy itself to the directory "documents" and then delete the one from executed directory (which in my case is desktop) after running the new one in documents.
Process: Run > Move to C://Documents > Start .EXE in documents > Delete the .EXE from the executed directory.
Sorry if this may come across hard to understand for some people I tried my best to specifically state what I wanted to accomplish.
I hope you can write the program in this way which will help.
1) program
i) Check if the program's execution directory is not C:/Documents
then it should copy the folder and put it in C:/Documents
and start the exe inside the documents
ii) else get a running list of the exe and their execution directory
(if its not C:/Documents stop the exe, and delete the execution folder
not sure if this will help , but just this is my thought
There's no way to do this with a single process as the exe which you want to move is going to be running in memory.
You could make the application copy itself, execute the copy, then kill itself.
this will definitely need to be tweaked and is very basic, but hopefully will give you some idea. sorry that it's all statics in a console application, all the methods should be in their own appropriate class.
using System;
using System.Globalization;
using System.IO;
using System.Linq;
namespace StackExchangeSelfMovingExe
{
class Program
{
static void Main(string[] args)
{
// check if we are running in the correct path or not?
bool DoMoveExe = !IsRunningInDocuments();
string runningPath = Directory.GetCurrentDirectory();
if (DoMoveExe)
{
// if we get here then we are not, copy our app to the right place.
string newAppPath = GetDesiredExePath();
CopyFolder(runningPath, newAppPath);
CreateToDeleteMessage(newAppPath, runningPath); // leave a message so new process can delete the old app path
// start the application running in the right directory.
string newExePath = $"{GetDesiredExePath()}\\{System.AppDomain.CurrentDomain.FriendlyName}";
ExecuteExe(newExePath);
// kill our own process since a new one is now running in the right place.
KillMyself();
}
else
{
// if we get here then we are running in the right place. check if we need to delete the old exe before we ended up here.
string toDeleteMessagePath = $"{runningPath}\\CopiedFromMessage.txt";
if (File.Exists(toDeleteMessagePath))
{
// if the file exists then we have been left a message to tell us to delete a path.
string pathToDelete = System.IO.File.ReadAllText(toDeleteMessagePath);
// kill any processes still running from the old folder.
KillAnyProcessesRunningFromFolder(pathToDelete);
Directory.Delete(pathToDelete, true);
}
// remove the message so next time we start, we don't try to delete it again.
File.Delete(toDeleteMessagePath);
}
// do application start here since we are running in the right place.
}
static string GetDesiredExePath()
{
// this is the directory we want the app running from.
string userPath = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
return $"{userPath}\\documents\\MyExe".ToLower();
}
static bool IsRunningInDocuments()
{
// returns true if we are running from within the root of the desired directory.
string runningPath = Directory.GetCurrentDirectory();
return runningPath.StartsWith(GetDesiredExePath());
}
// this copy method is from http://stackoverflow.com/questions/58744/best-way-to-copy-the-entire-contents-of-a-directory-in-c-sharp
public static void CopyFolder(string SourcePath, string DestinationPath)
{
if (!Directory.Exists(DestinationPath))
{
Directory.CreateDirectory(DestinationPath);
}
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*",
SearchOption.AllDirectories))
Directory.CreateDirectory(DestinationPath + dirPath.Remove(0, SourcePath.Length));
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*",
SearchOption.AllDirectories))
File.Copy(newPath, DestinationPath + newPath.Remove(0, SourcePath.Length), true);
}
private static void CreateToDeleteMessage(string newPath, string runningPath)
{
// simply write a file with the folder we are in now so that this folder can be deleted later.
using (System.IO.StreamWriter file =
new System.IO.StreamWriter($"{newPath}\\CopiedFromMessage.txt", true))
{
file.Write(runningPath);
}
}
private static void ExecuteExe(string newExePath)
{
// launch the process which we just copied into documents.
System.Diagnostics.Process.Start(newExePath);
}
private static void KillMyself()
{
// this is one way, depending if you are using console, forms, etc you can use more appropriate method to exit gracefully.
System.Diagnostics.Process.GetCurrentProcess().Kill();
}
private static void KillAnyProcessesRunningFromFolder(string pathToDelete)
{
// kill any processes still running from the path we are about to delete, just incase they hung, etc.
var processes = System.Diagnostics.Process.GetProcesses()
.Where(p => p.MainModule.FileName.StartsWith(pathToDelete, true, CultureInfo.InvariantCulture));
foreach (var proc in processes)
{
proc.Kill();
}
}
}
}

Faulty file in use error

This code is the first code in my Form_Load method:
DirectoryInfo dir =new DirectoryInfo("d:\\themes.thumb");
string[] animals = new string []
{
"Snakes",
"SnowyOwls",
"Tigers",
"TropicalFish",
"WildBeauty",
"Wolves"
};
foreach (FileInfo fil in dir.GetFiles())
{
for(int ii=0;ii<animals.Length;ii++)
{
if (fil.Name.StartsWith(animals[ii]))
{
try
{
fil.Replace(fil.FullName,fil.FullName.Replace(fil.Name,"Animals-" + fil.Name));
}
catch
{
}
}
}
and I'm getting the following error whenever if (fil.Name.StartsWith(animals[ii])) is true:
The process cannot access the file because it is being used by another process.
What is wrong as I have not opened any files before this code?
You should seperate your reading logic from your update logic.
for example:
var replacements = dir.GetFiles()
.Where(file => animals.Any(animal => file.Name.StartsWith(animal)))
.Select(file => new
{
OldFullName = file.FullName,
NewFullName = file.FullName.Replace(file.Name, "Animals-" + file.Name)
})
.ToList();
foreach (var replacement in replacements)
{
File.Move(replacement.OldFullName, replacement.NewFullName);
}
Your replace logic has some subtle bugs (what happens with files that are in a folder called "Wolves" for example?) you may wan to work that out.
It looks like you are misunderstanding how to use the FileInfo.Replace method.
fil.Replace(fil.FullName,fil.FullName.Replace(fil.Name,"Animals-" + fil.Name));
Here you are actually trying to overwrite fil's contents with itself. That explains the error message.
You might want to read the documentation a bit more closely.
EDIT:
To be absolutely clear: FileInfo.Replace is not meant to be used to perform file renames. It's meant to replace file contents. To perform a rename, you use FileInfo.MoveTo.
Get LockHunter. It's a free tool which shows you which process is holding onto a particular file or folder. I found it really useful.
Microsoft Process Explorer is also free and can also find open handles (Ctrl+F) by name.

How do I extract a SubDirectory using C# DotNetZip?

I have MyFile.zip that has a main directory "MyMainFolder", and several SubDirectories inside of that, one of which I want to extract (MySubFolder)...with all of its subdirs and contents.
I am trying to figure out how to 'step-into' the MyMainFolder , so that I can extract 'MySubFolder'.
I have some code that will extract a folder as long as that folder I am looking for exists as the main folder in the zip...and I can detect if the main folder is called "MyMainFolder" so it knows to look inside that and extract from there rather than looking in the main zip root for MySubFolder).
using (ZipFile zip1 = ZipFile.Read(fileName))
{
zipFile = ZipFile.Read(#""+fileName);
var result = zipFile.Any(entry => entry.FileName.Contains("MySubFolder"));
if (result == false)
{
MessageBox.Show("MyMainFolder detected....Extracting from MyMainFolder...");
// something here that will extract JUST MySubFolder and contents
} else {
foreach (var e in selection)
{
var selection = (from e in zip1.Entries where (e.FileName).Contains("NySubfolder") select e)
e.Extract(outputDirectory);
}
}
}
So far, I have tried putting a separate using inside each part of the if-else, and I tried creating a seperate selectionX in which I tried to force the root-folder name (which will always be 'MyMainFolder' for this experiment) to be part of what it looked through, thinking I could then extract MySubFolder, but I couldn't get that to work either. I tried to incorporate several other methods I found on stackflow and elsehwere, like using parts of 'how to extract files, but ignoring the path in the zipfile' and other such posts to try and find a way to 'skip' over that main root folder when extracting. (so that it gets ONLY 'MySubFolder' (and contents) and extracts to outputDirectory (not MyMainFolder\MySubFolder...)
Any help is appreciated.
Thanks!!
Enumerating though the entire contents until I came across what I was looking for worked, but just as an experiment, I wanted to see if it could be done another way.
Since I was unable able to check the names of the subfolders inside a root folder, I figured I could just match what I was looking for as I was parsing through it, extracting only what I wanted to, and then just change the output path.
using (ZipFile zip1 = ZipFile.Read(fileName))
{
zipFile = ZipFile.Read(#""+fileName);
var result = zipFile.Any(entry => entry.FileName.Contains("MySubFolder"));
if (result == false)
{
// something here that will extract JUST MySubFolder and content
string TestX = Path.GetDirectoryName(e.FileName) ;
string MyNewPath = outputDirectory+#"\"+TestX ;
e.Extract(MyNewPath);
} else {
foreach (var e in selection)
{
var selection = (from e in zip1.Entries where (e.FileName).Contains("MySubfolder")
.select e)
e.Extract(outputDirectory);
}
}
Something like that..
Not very useful, but interesting and helped me learn a little.
(if nothing else, an example of how NOT to do things..hehe)
Thanks

Categories