How to save an stringbuilder's content to text file using SaveFileDialog? - winforms

This is a winforms application.
In windows, I want the user to click and button, and then a popup should make the user select the path of where they want to save the file.

You want the WriteAllText function.
using (SaveFileDialog dialog = new SaveFileDialog()) {
if (dialog.ShowDialog(this) == DialogResult.OK) {
File.WriteAllText(dialog.FileName, yourStringBuilder.ToString());
}
}

Think no longer...
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication2 {
public partial class Form1 : Form {
StringBuilder sb = new StringBuilder();
public Form1() {
InitializeComponent();
sb.Append("This is going ");
sb.Append("to be saved to a text file");
}
private void button1_Click(object sender, EventArgs e) {
using (SaveFileDialog dlg = new SaveFileDialog()) {
if (dlg.ShowDialog() == DialogResult.OK) {
string fileName = dlg.FileName;
SaveToFile(fileName);
}
}
}
private void SaveToFile(string fileName) {
System.IO.TextWriter w = new System.IO.StreamWriter(fileName);
w.Write(sb.ToString());
w.Flush();
w.Close();
}
}

StringBuilder.ToString() will get you the string.
This link will show you how to write text to a file.
This link will show you how to call SaveFileDialog and pass a stream to it to save.
Hope that helps.

StringBuilder.ToString() can be passed to the TextStream.Write() method after creating the file.
Using the SaveFileDialog class, you can let the user select path and file name - in a standard way. Detailed examples in the doc.

Related

Close/cancel open X509Certificate2UI certificate selection and pin dialog programmatically without further user interaction

I have a function that is executed in a C# Task object (part of a Winforms .NET 4.7.2 application) that asks the user to select a certificate from the windows certificate store using the X509Certificate2UI class.
There can be a situation where the corresponding selection dialog is open and waiting for user input when the task is canceled using the cancellation token. My expectation was that the selection dialog would then be automatically closed/canceled too, but it remains open.
The same problem applies to the dialog for entering the PIN securing the private key of a certificate.
Is there any clean way to cancel the dialog programmatically or to assure that it closes with the task?
The following code demonstrates the problem. One task opens the selection dialog. A second task simulates an event triggered after the dialog is opened. Once DoSomethingDifferent is done, the certificate is not required anymore and the selection dialog should therefore be closed. It however stays open until the program exits.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace CancelCertificateDialog
{
class Program
{
private static X509Certificate2 SelectCertificate()
{
// Selecte certificate from store
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
X509Certificate2Collection collection = (X509Certificate2Collection)store.Certificates;
X509Certificate2Collection selectedCertificate = (X509Certificate2Collection)collection.Find(X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, false);// (X509FindType.FindByKeyUsage, X509KeyUsageFlags.DigitalSignature, true);
selectedCertificate = X509Certificate2UI.SelectFromCollection(
store.Certificates,
"Certficates",
"Select a certificate for signing the document",
X509SelectionFlag.SingleSelection);
return selectedCertificate[0];
}
private static void DoSomethingDifferent()
{
Thread.Sleep(4000);
Console.WriteLine("I'm done");
}
static void Main(string[] args)
{
Console.WriteLine("Start");
CancellationTokenSource tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
Task<X509Certificate2> t1 = new Task<X509Certificate2>(() => SelectCertificate(), token);
Task t2 = new Task(() => DoSomethingDifferent(), token);
t1.Start();
t2.Start();
try
{
Task.WaitAny(t1, t2);
}
catch (AggregateException e)
{
for (int j = 0; j < e.InnerExceptions.Count; j++)
{
Console.WriteLine(e.InnerExceptions[j]);
}
}
Console.WriteLine("The certificate is not required anymore. Get rid of the dialog");
tokenSource.Cancel();
Console.WriteLine("Press Key");
Console.ReadKey();
}
}
}

render pdf from memorystream

I have searched for entire day for a solution, but somehow I couldn't find it.
What I wanted is to get data from database (binary file such as PDF) into MemoryStream (which I succeeded to do so), but problem is when I wish to preview that file into WebBrowser control.
so the code goes:
using System;
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.Data.SqlClient;
using System.IO;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
MemoryStream memory = new MemoryStream();
//byte[] temp;
private void Form1_Load(object sender, EventArgs e)
{
memory = GetBlobFile();
}
private MemoryStream GetBlobFile()
{
MemoryStream ms = new MemoryStream();
string SQL = "SELECT [SnapshotPDF] FROM [DBtest].[dbo].[SamplePDF] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=database;Initial Catalog=DBtest; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
byte [] result = (byte[])comm.ExecuteScalar();
conn.Close();
if (result != null)
{
ms.Write(result, 0, result.Length);
ms.Position = 0;
}
return ms;
}
private void button1_Click(object sender, EventArgs e)
{
//webBrowser1.DocumentText = "application/pdf";
webBrowser1.DocumentStream = memory;
}
}
}
Actually webBrowser really output content from memory, but obviously from picture above it's rendered as text...
How can I force to render as PDF?
If it is not possible to use webBrowser control, is there any other controls that I can use in WinForms that would preview/render PDF from memory.
You have to implement an async pluggable protocol, e.g. IClassFactory, IInternetProtocol... Then you use CoInternetGetSession to register your protocol. When IE calls your implementation, you can serve your image data from memory/provide mime type.
It's a bit tedious, but doable. Look at IInternetProtocol and pluggable protocols documentation on MSDN.
Done, I found one little bug which I correct it. this is entire code:
using System;
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.Data.SqlClient;
using System.IO;
using Ghostscript.NET;
using Ghostscript.NET.Viewer;
namespace MemoryStreamTest
{
public partial class Form1 : Form
{
Stream stream;
byte[] result;
private GhostscriptViewer _viewer;
private GhostscriptVersionInfo _gsVersion = GhostscriptVersionInfo.GetLastInstalledVersion();
private Bitmap _pdfPage = null;
public Form1()
{
InitializeComponent();
pictureBox1.Width = 100;
pictureBox1.Height = 100;
_viewer = new GhostscriptViewer();
_viewer.DisplaySize += new GhostscriptViewerViewEventHandler(_viewer_DisplaySize);
_viewer.DisplayUpdate += new GhostscriptViewerViewEventHandler(_viewer_DisplayUpdate);
_viewer.DisplayPage += new GhostscriptViewerViewEventHandler(_viewer_DisplayPage);
}
private void Form1_Load(object sender, EventArgs e)
{
GetBlobFile();
}
private void GetBlobFile()
{
string SQL = "SELECT [SnapshotPDF] FROM [test].[dbo].[InvoiceAdded] WHERE id = " + 21;
SqlConnection conn = new SqlConnection("Data Source=test;Initial Catalog=test; User ID=test; Password=test;");
SqlCommand comm = new SqlCommand(SQL, conn);
conn.Open();
result = (byte[])comm.ExecuteScalar();
conn.Close();
stream = new MemoryStream(result);
}
private void button1_Click(object sender, EventArgs e)
{
ConvertToBitmap();
}
private void ConvertToBitmap()
{
_viewer.Open(stream, _gsVersion, true);
}
//DisplayPage
void _viewer_DisplayPage(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
//DisplaySize - dynamically
void _viewer_DisplaySize(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Image = e.Image;
}
//DisplayUpdate - automatic update picture
void _viewer_DisplayUpdate(object sender, GhostscriptViewerViewEventArgs e)
{
pictureBox1.Invalidate();
pictureBox1.Update();
}
}
}
keep in mind that for this I needed to add .dll from Ghostscript.NET (a nice wrapper made by my patriot from Croatia), also I needed to install Ghostscript interpreter from GhostScript interpreter
And also many thanks to user: sm.abdullah
which actually point me to right direction.
Cheers

System.Windows.Shapes.Path incorrect behavior

After doing some research on subject I didn't find anything, so I'm sorry if the same question was already asked.
Task: make a colored track-line on Canvas after cursor, when the left mouse button is pressed (like brush in Paint).
Problem: I think using System.Windows.Shapes.Path is the best approach to doing this task. Code below works fine, except for one thing: if you try to move your cursor then change direction to the opposite (e.g. the value on X-axis increases, then decreases, but the value on Y-axis, stays constant), you will get an unexpected part of Line, corresponding to the previous direction.
I'm sorry for the tangled description of my problem, but I hope you will get it.
To make it easier for you to reproduce it on your machine I'm adding the solution.
Please, point out for my mistake if I did one!
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApplication3
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Boolean Inserting;
private Path path;
private Boolean isFirstPoint;
public MainWindow()
{
InitializeComponent();
LolCanvas.IsHitTestVisible = true;
}
private void Canvas_MouseMove(object sender, MouseEventArgs e)
{
if (Inserting)
{
Point p = Mouse.GetPosition(LolCanvas);
if (isFirstPoint)
{
PathFigure myPathFigure = new PathFigure();
myPathFigure.StartPoint = new Point(p.X + 5, p.Y + 5);
myPathFigure.Segments = new PathSegmentCollection();
(path.Data as PathGeometry).Figures.Add(myPathFigure);
isFirstPoint = false;
}
else
{
LineSegment myLineSegment = new LineSegment();
myLineSegment.Point = new Point(p.X + 5, p.Y + 5);
(path.Data as PathGeometry).Figures[0].Segments.Add(myLineSegment);
}
}
}
private void Canvas_MouseDown(object sender, MouseButtonEventArgs e)
{
Inserting = true;
path = new Path();
path.Stroke = new SolidColorBrush(Colors.Red);
path.StrokeThickness = 50;
path.Data = new PathGeometry();
(path.Data as PathGeometry).Figures = new PathFigureCollection();
LolCanvas.Children.Add(path);
isFirstPoint = true;
}
private void Canvas_MouseUp(object sender, MouseButtonEventArgs e)
{
Inserting = false;
}
}
}
Xaml:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Canvas x:Name="LolCanvas" MouseMove="Canvas_MouseMove" MouseDown="Canvas_MouseDown" MouseUp="Canvas_MouseUp" Background="Black">
</Canvas>
</Window>
Link to the application: http://ge.tt/99aSgyo/v/0?c
Apparently this kind of behavior is correct for path. The problem appeared because of the angle between line parts. It was 180 degrees, so window couldn't render Path propertly in this place.
I had two ways to defeat it:
1) Set IsSmoothJoin property to true for each line segment.
2) Make another Path object, when this kind of problem might occur

Passing Variables From File-to-File in C#

How would I use a variable declared in Program.cs and access it's value from Form1.cs?
I know how to do this in C, but I'm completely lost in Microsoft's little twist on C.
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
static class Program
{
public static Lua lua = null;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
lua = new Lua();
}
}
}
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using LuaInterface;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
lua.DoString("print('hi')");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
textBox1.Text = "";
}
}
}
Using your examples of Program.cs and Form1.cs and assuming these are the default names and that you have a Program class that instantiates a Form1 class and that you want to pass a parameter to the Form1 class, you can do the following:
Define a constructor for Form1 that takes this parameter and chain to the default constructor:
private Lua lua;
public Form1(Lua lua) : this()
{
this.lua = lua;
}
In your Program class when instantiating Form1, pass the parameter to it:
lua = new Lua();
Application.Run(new Form1(lua));
Note that I am using OOP terminology - objects and classes (not files).
Update:
Since you have declared your lua variable as a public static member of the Program class, you can access it anywhere in your program (assuming the namespaces have been declared appropriately) as follows:
Program.lua;
Though you would want to instantiate the static field before calling Application.Run.
In any way, this makes the object a public shared resource across all threads - making it virtually untestable and difficult to work with if you go multi-threaded.
You can also access the parameter with
Program.lua;
But Oded's way is cleaner.
And in Main, the object must be instantiated before Application.Run:
static void Main()
{
lua = new Lua();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
In Program.cs there is most probably a static class defined like this:
static class Program
{
...
}
If you declare the variable as public or internal, you will be able to access it from your form.
static class Program
{
public static int myVariable;
public static int MyProperty { get; set; }
}
In your form, you access the variable and the property with:
int i = Program.myVariable;
int j = Program.MyProperty;
In object-oriented programming, you would usually keep the variables private and only declare the properties as public.

A simple WPF Authentication

How to create a simple WPF Authentication for WPF application?
For example:
First time a user should registry then login.
Users login and password should be saved as txt file(encrypted).
If process of authentication is successful,then it should redirect to another existed window.
I'm a beginner in WPF.
I've searched about this question,but didn't find what I need.
I need a simple,step by step explanation of how to do it.
Thanks in advance! :)
I am also learning so in order to exercise a bit i have created a very simple example for you. It is probably unprofessional and unsafe but i think (hope) it is possible to extend it somehow :).
Firstly you need to create simple WPF windows (use txt/btn+Name naming convention):
For both windows add
using System.IO;
Then you need to add events for buttons and modify code for both windows:
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
// This is really bad/weak encryption method
String WeakDecryptMethod(String textIn)
{
Char[] temp = textIn.ToArray<Char>();
for (int i = 0; i < textIn.Length; i++)
{
temp[i] = (char)((int)temp[i] - 3);
}
return new String(temp);
}
private void btnRegister_Click(object sender, RoutedEventArgs e)
{
RegisterWindow newWindow = new RegisterWindow();
newWindow.ShowDialog();
}
private void btnOK_Click(object sender, RoutedEventArgs e)
{
// If file exist and login and password are "correct"
if (File.Exists("Users.txt")
&& txtLogin.Text.Length >= 4
&& txtPass.Text.Length >= 4)
{
using (StreamReader streamReader = new StreamReader("Users.txt"))
{
// While there is something in streamReader read it
while (streamReader.Peek() >= 0)
{
String decryptedLogin = WeakDecryptMethod(streamReader.ReadLine());
String decryptedPass = WeakDecryptMethod(streamReader.ReadLine());
if (decryptedLogin == txtLogin.Text && decryptedPass == txtPass.Text)
{
ProtectedWindow protectedWindow = new ProtectedWindow();
this.Close();
protectedWindow.Show();
break;
}
}
}
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
And code for Register window:
public partial class RegisterWindow : Window
{
public RegisterWindow()
{
InitializeComponent();
}
// This is really bad/weak method to encrypt files
String WeakEncryptMethod(String textIn)
{
Char[] temp = textIn.ToArray<Char>();
for (int i = 0; i < textIn.Length; i++)
{
temp[i] = (char)((int)temp[i] + 3);
}
return new String(temp);
}
private void btnRegister_Click(object sender, RoutedEventArgs e)
{
// If file exist and login and password are "correct"
if (File.Exists("Users.txt")
&& txtLogin.Text.Length >= 4
&& txtPass.Text.Length >= 4
&& txtPass.Text == txtPassCheck.Text)
{
StringBuilder stringBuilder = new StringBuilder();
using (StreamReader streamReader = new StreamReader("Users.txt"))
{
stringBuilder.Append(streamReader.ReadToEnd());
}
using (StreamWriter streamWriter = new StreamWriter("Users.txt"))
{
streamWriter.Write(stringBuilder.ToString());
streamWriter.WriteLine(WeakEncryptMethod(txtLogin.Text));
streamWriter.WriteLine(WeakEncryptMethod(txtPass.Text));
}
this.Close();
}
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
In order to work application need to have access to file "Users.txt" which needs to be placed in the same folder.
Notes:
It will be better if you will use some proper encryption functions and probably create separate class for it. Additionally i am almost sure that it will not work properly with login and password which contains the last 3 characters from the end of ASCII tables.
In my opinion it is a bad idea to store login and password data in *.txt file :).
As far i know C# code is very easily reverse engineered so probably it will be better to hide encryption/decryption part somehow. I do not know much about it, but u will be able to read more [here] 2 and probably uncle Google will be able to help.
Code is very simple and there is probably a lot of possibilities to extend it (more file handling stuff, TextBox validation for proper input and password strength calculations)

Resources