I am writing a game in Unity3D and I was wondering if there are any tools available to check a server for an update, if so, download and install the update.
I have been trying to write my own, however I am stuck on the "Download and Install" part.
This is what I have:
//Unity3D Patching Tool v0.1
using UnityEngine;
using System.Collections;
public class Patcher : MonoBehaviour {
public const string VERSION = "1.0"; // The version of the program that is running
private string patchUrl = "http://yoursite.com/patchversion.html"; //a website with the current build number
//a template to find the current build for windows
private const string UPDATE_WINDOWS_URL_TEMPLATE = "http://yoursite.com/release/build[[[BUILD_NUMBER]]].exe";
//a template to find the current build for mac
private const string UPDATE_MAC_URL_TEMPLATE = "http://yoursite.com/release/build[[[BUILD_NUMBER]]].app";
IEnumerator Start() {
/*
* Check for patch
*/
WWW patchwww = new WWW(patchUrl); //create new web connection to the build number site
yield return patchwww; // wait for download to finish
if (patchwww.text == VERSION){ //check version
Debug.Log("Up To Date");
}
else {
Debug.Log("Download New Update");
WWW downloadwww = new WWW(DownloadUpdate(patchwww.text)); // generates link to current build and downloads
yield return downloadwww;
}
}
private string DownloadUpdate(string version){
string versionNumber = version.Replace(".", ""); //remove periods in version number
string buildToDownload = "";
/*
* Check Platform and Set URL
*/
switch (Application.platform){
case RuntimePlatform.WindowsEditor:
case RuntimePlatform.WindowsPlayer:
Debug.Log("Windows " + Application.platform);
buildToDownload = UPDATE_WINDOWS_URL_TEMPLATE.Replace("[[[BUILD_NUMBER]]]", versionNumber);
break;
case RuntimePlatform.OSXEditor:
case RuntimePlatform.OSXPlayer:
Debug.Log("Mac " + Application.platform);
buildToDownload = UPDATE_MAC_URL_TEMPLATE.Replace("[[[BUILD_NUMBER]]]", versionNumber);
break;
}
Debug.Log(buildToDownload);
return buildToDownload;
}
}
I have something similar, I have the http download a text file that has the latestversion within it, if their version is lower then this, they have the option to download an installer
if you are using this on windows, you could then have unity run a external process ( a simple c# form that updates your files, or that downloads a installer waits for it to complete then executes it) [probably possible within unity as well, but this works well for me]
(you could also just point the process at the web browser with the link to the latest version this way the browser or their default file downloader will be responsible for downloading the program and will handle communication errors) this way they would know that they need to open the installed app once it is complete
import System.Diagnostics;
var path:String = "somewhere";
var foo:Process = new Process();
function Start()
{
foo.StartInfo.FileName = "someprogram";
foo.StartInfo.Arguments = path;
foo.Start();
}
Related
I'm working on a Unity app right now, and the client wants to be able to allow the user to click a button and have a PDF open on the phone (iOS and Android), but in whatever app they use for reading PDFs and not inside of the Unity app.
I've tried Application.OpenURL("file:///[...]"), and that works in the editor on my Windows desktop (opens PDF in Edge)... but it doesn't open the file on Android (nothing happens to open the file).
Here's what I'm doing:
public string FileName = string.Empty;
public string FileExtension = string.Empty;
private string FilePath = string.Empty;
void Start()
{
FilePath = string.Format("{0}/{1}.{2}", Application.persistentDataPath, FileName, FileExtension);
}
public void OpenFile()
{
if (!File.Exists(FilePath))
{
var pathRoot = Application.streamingAssetsPath;
#if UNITY_ANDROID && !UNITY_EDITOR
pathRoot = Application.dataPath + "!/assets";
#endif
StartCoroutine(FetchFile(string.Format("{0}/{1}.{2}", pathRoot, FileName, FileExtension)));
return;
}
Application.OpenURL(FilePath);
}
private IEnumerator FetchFile(string path)
{
path = "file://" + path;
#if UNITY_ANDROID && !UNITY_EDITOR
path = "jar:" + path;
#endif
var fetcher = new WWW(path);
yield return fetcher;
File.WriteAllBytes(FilePath, fetcher.bytes);
Application.OpenURL("file:///" + FilePath);
}
So I'm checking if the file exists on the device in storage, and if not I am 'extracting' it from the app and writing it to storage. Then I try to open the local 'URL' with the file:/// standard (this Application.OpenURL("https://www.google.com"); does work successfully to open that URL in my mobile browser).
Is there a way in Unity to create an Intent or something to trigger this? The FilePath works on Windows, and is the same path I am writing the bytes to, so that should be correct... or am I missing something?
NOTE: this is also not working in iOS, but I thought I read in the Unity forums (can't find the link now) to Android being the only exception to the paths/URL thing... can anyone help me out with that, too?
If you are trying to open any document using Application.OpenURL then it won't work. Unity removed that support in latest versions. You can use AndroidOpenUrl.OpenUrl(documentUrl, dataType) to resolve this issue.
public void Example()
{
string dataType = "application/pdf";
string documentUrl = "/storage/emulated/0/Downloads/template.pdf";
AndroidOpenUrl.OpenUrl(documentUrl, dataType); // you can specify any MIME type when opening a file by explicitly specifying the dataType parameter
}
You will get a demo and installation steps of the package from the following repository.
https://github.com/codemaker2015/Unity-Android-Files-Opener
Android permissions changed in Nougat (v.7)
you won't be able to open by path only, the sistem was blocking it.
Just lower the target API level to 23 (Android 6.0 'Marshmallow').
you could just use this code as per this reference URL:
How to Open a PDF in an Android-Unity3D App?
void openPDF(){
string namePDF = "test";
TextAsset pdfTem = Resources.Load("PDFs/"+namePDF, typeof(TextAsset)) as TextAsset;
System.IO.File.WriteAllBytes(Application.persistentDataPath + "/"+namePDF+".pdf", pdfTem.bytes);
Application.OpenURL(Application.persistentDataPath+"/"+namePDF+".pdf");
}
I am working on windows application project and from that project want to build different multiple c# projects which are in one solution of visual studio 2015 and also want them to be build programmatically individually using MSBuild tool without using command prompt and finally want to show the output in log file not in command prompt (means those project is building successfully or having any errors like this message in log file)
Do I need to use any MSBuild API and how to add in this project?
I have seen many questions like this (not exactly same) but it didn't work for me. please can anybody help me with this?
using Microsoft.Build.Evaluation;
using Microsoft.Build.Execution;
using Microsoft.Build.Logging;
...
public static BuildResult Compile(string solution_name, out string buildLog)
{
buildLog = "";
string projectFilePath = solution_name;
ProjectCollection pc = new ProjectCollection();
Dictionary<string, string> globalProperty = new Dictionary<string, string>();
globalProperty.Add("nodeReuse", "false");
BuildParameters bp = new BuildParameters(pc);
bp.Loggers = new List<Microsoft.Build.Framework.ILogger>()
{
new FileLogger() {Parameters = #"logfile=buildresult.txt"}
};
BuildRequestData buildRequest = new BuildRequestData(projectFilePath, globalProperty, "4.0",
new string[] {"Clean", "Build"}, null);
BuildResult buildResult = BuildManager.DefaultBuildManager.Build(bp, buildRequest);
BuildManager.DefaultBuildManager.Dispose();
pc = null;
bp = null;
buildRequest = null;
if (buildResult.OverallResult == BuildResultCode.Success)
{
Console.ForegroundColor = ConsoleColor.Green;
}
else
{
if (Directory.Exists("C:\\BuildResults") == false)
{
Directory.CreateDirectory("C:\\BuildResults");
}
buildLog = File.ReadAllText("buildresult.txt");
Console.WriteLine(buildLog);
string fileName = "C:\\BuildResults\\" + DateTime.Now.Ticks + ".txt";
File.Move("buildresult.txt", fileName);
Console.ForegroundColor = ConsoleColor.Red;
Thread.Sleep(5000);
}
Console.WriteLine("Build Result " + buildResult.OverallResult.ToString());
Console.ForegroundColor = ConsoleColor.Gray;
Console.WriteLine("================================");
return buildResult;
}
This is some old code I had lying around.
I use this to programatically build solutions and C# Projects. The output will be a BuildResult.Success or BuildResult.Failure.
The variable buildLog will contain the build output.
Note - the only way to access the build output that I am aware of is to use the above methodology of having a log file generated and then reading it in your C# code.
One thing to be aware of and I never did find a fix for this, is that the application that runs this code, may keep dll's it loads into memory from nuget package directories in memory. This makes deleting those directories problematic. I found a work around by having my application run as a MS Service - it seems when it runs as a local service, it has enough permissions to delete files held in memory.
My company has purchased the CoolUtils TotalPDFPrinterX from https://www.coolutils.com/TotalPDFPrinterX
I make an HTTP PUT from Postman to the API and I get “Could not get any response”.
When running on my Windows machine the PDF prints fine however on the server the site crashes and in the event log I get the error "A process serving application pool '[MY_APP_POOL]' failed to respond to a ping. The process id was '[MY_PROCESS_ID]'."
Here is my C# code:
PDFPrinterX ppx = new PDFPrinterX();
ppx.Print(fileName, printerName, "-ap Default");
if (ppx.ErrorMessage != null)
{
WriteToSQL(id, false, ppx.ErrorMessage, 2);
Console.WriteLine(ppx.ErrorMessage);
}
By writing to the event log I know the site crashes on this line: PDFPrinterX ppx = new PDFPrinterX(); I have also surrounded the above code with a try catch and no exception is thrown. The site still crashes.
Things I have tried:
Uninstalling and Reinstalling the CoolUtils software
Giving EVERYONE Full control to the site folder and the CoolUtils program folder
Creating a C# desktop application using the same code. THIS WORKS FINE ON THE SERVER. It's just the ASP site that crashes.
Does anyone know what might be causing this?
The more I research this thing online the more I'm inclined to say that ActiveX which is the X in PDFPrinterX doesn't seem to work well when hosted in IIS.
I've seen a few forums where they say it works fine when they debug on localhost but when deployed to server is crashes.
...works fine when used inside localhost(Visual studio)
One of their feature pages shows that it requires Win 2000/NT/XP/2003/Vista/7
You should look into whether your server supports ActiveX components that can work in conjunction with IIS.
Looking at one of their other products support page: TotalPDFConverterX:
the following note in my opinion may also apply to TotalPDFPrinterX, given its dependency on ActiveX as well.
Note: Pay attention to some details during installation Total PDF Converter X:
Do not forget to register ActiveX in your web-server account.
Total PDF Converter X supports only Internet Explorer, Mozilla and Firefox browsers.
ActiveX works only with 32-bit internet information server. 64-bit server is not supported. Use command line version instead.
Thanks to #Nkosi I was able to find a workaround.
ActiveX works only with 32-bit internet information server. 64-bit server is not supported. Use command line version instead.
Our IIS server is 64 bit so that is what probably caused the site to hang up.
Buttt... the command line still worked in printing the PDFs on the server.
Client side code (makes the HTTP POST):
private void SendToPrinter(string fileName, string printerName, int id, decimal documentSequence)
{
// use http client to make a POST to the print api
using (var client = new HttpClient())
{
// compile the values string to transfer in POST
// should finish to look something like this:
// C:\print.pdf&PRTFTW_OFIT&ValShip-155320-1
var values = new Dictionary<string, string>
{
{ "", fileName + "&" + printerName + "&ValShip-" + id + "-" + documentSequence},
};
// URL encode the values string
var content = new FormUrlEncodedContent(values);
// make the POST
// DEBUG
var response = client.PostAsync("http://localhost:54339/api/print", content);
// retrieve the response
var responseString = response.Result.ToString();
}
}
Server side code (receives the HTTP POST):
using System;
using System.Net.Http;
using System.Web;
using System.Web.Http;
namespace api.valbruna.print.Controllers
{
public class PrintController : ApiController
{
// POST api/print
public HttpResponseMessage Post(HttpRequestMessage request)
{
try
{
// parse the content recieved from the client
var content = request.Content.ReadAsStringAsync().Result;
// decode the content, certain characters such as
// '&' get encoded to URL lingo such as '%26'
content = HttpUtility.UrlDecode(content);
// split the string into 3 seperate parts
String[] str = content.Split('&');
// remove the equal sign from the first string
str[0] = str[0].Trim('=');
// compile the arguments command line string
// should finish to look something like this:
// "C:\Program Files (x86)\CoolUtils\Total PDF PrinterX\PDFPrinterX.exe" "C:\print.pdf" -p"\\PRINTERS\PRTFTW_OFIT" -ap Default -log "C:\inetpub\logs\CoolUtils\log-ValShip-155320-4.txt" -verbosity detail"
String arguments = "\"" + str[0] + "\" -p\"\\\\PRINTERS\\" + str[1] +
"\" -ap Default -log \"C:\\inetpub\\logs\\CoolUtils\\log-" + str[2] +
".txt\" -verbosity detail";
// file location for PDFPrinterX.exe
String file = #"C:\Program Files (x86)\CoolUtils\Total PDF PrinterX\PDFPrinterX.exe";
// start the process
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
startInfo.FileName = file;
startInfo.Arguments = arguments;
process.StartInfo = startInfo;
process.Start();
return new HttpResponseMessage() { Content = new StringContent(content) };
}
catch (Exception e)
{
return new HttpResponseMessage() { Content = new StringContent(e.Message) };
}
}
}
}
I want to make an application - license plate recognition from image. I use OpenCvSharp and Puma.NET.
But when I start my application,writes that the number is not found.
When I use breakpoints - Exception - "Recognition engine halted with code:0"
I loaded three dll - dibapi.dll, puma.net.dll, puma.interop.dll.
Why numbers are not recognized?
public void RecognizePlate() //
{
plateList.Clear();
int i = 1;
foreach(var plateImage in plate)
{
plateList.Add(i.ToString()+ " ) " + RunPuma(plateImage));
i++;
}
}
string RunPuma(IplImage img) //
{
PumaPage Image = new PumaPage(img.ToBitmap());
using (Image)
{
Image.FileFormat = PumaFileFormat.RtfAnsi;
Image.AutoRotateImage = true;
Image.FontSettings.DetectBold = true;
Image.FontSettings.DetectItalic = true;
Image.EnableSpeller = false;
Image.Language = PumaLanguage.English;
try
{
string s = Image.RecognizeToString();
return s;
}
catch(Exception e)
{
return "This is NOT NUMBER";
}
}
return "Error";
}`
You will need to restart Visual Studio as Administrator and you should be able to work then.
The problem is an unsuccessful registration.
According the documentation, apuma.dll component should be registered during the installation. But *.bat file seems to be wrong, at least for my computer.
I solved problem with:
moving all files from Puma.NET\COM Server\Register to Puma.NET\COM Server
open console in Puma.NET\COM Server directory.
Typing this command: regsvr32 APuma.dll
If you get a successful registration message, George is your uncle!!
I have a utility programs’s EXE file, when i run this file there is a winform only and there is button when we click on it, it run windows’s notepad. Now I want to hijack this program’s command to run notepad and instead of running notepad I want to run MS Word. I know C# and VB.NET. What I need to do this ?
You can try to add in folder with this program your own program called notepad.exe that should do only one thing: run word.
If you want to do it programatically in C then you should read this page - maybe it helps: Intercepted: Windows Hacking via DLL Redirection
You can use a trick to replace programs with another by making changes to the registry. This will work even if the program you are running uses absolute paths to run notepad. It overrides any instance of the running program with the chosen one no matter where it resides. And you won't have to patch the file. The key you'd be interested in is:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
Add a key with the name of the program and add a Debugger string with the path to the program you want to replace it with. Of course you need to have permissions to make the necessary modifications. This page explains how you can replace Windows Notepad with another program. You can apply the same process here.
Though you'll probably not want to have this permanent change, so you can write up a program to temporarily add/change the key, run your program then change it back. Here's a complete one I just whipped up to temporarily replace Notepad with Word for a demonstration. Seems to work perfectly fine (though as always, use at your own risk). Just make all the necessary changes to fit your situation.
using System.Diagnostics;
using Microsoft.Win32;
namespace ProgramLauncher
{
class Program
{
// change the following constants as needed
const string PROGRAM_NAME = #"notepad.exe";
const string REPLACEMENT_PATH = #"C:\Program Files (x86)\Microsoft Office\Office12\WINWORD.EXE";
const string RUNNING_PATH = #"C:\Windows\notepad.exe";
// root key
const string KEY = #"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options";
static void Main(string[] args)
{
using (var rootKey = Registry.LocalMachine.OpenSubKey(KEY, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
var oldPath = default(string);
var needsRestoration = false;
try
{
oldPath = BackupKey(rootKey, PROGRAM_NAME, REPLACEMENT_PATH);
needsRestoration = true;
Process.Start(RUNNING_PATH).WaitForExit();
}
finally
{
if (needsRestoration)
RestoreKey(rootKey, PROGRAM_NAME, oldPath);
}
}
}
static string BackupKey(RegistryKey rootKey, string programName, string newPath)
{
Debug.Assert(rootKey != null);
Debug.Assert(!string.IsNullOrEmpty(programName));
Debug.Assert(!string.IsNullOrEmpty(newPath) && System.IO.File.Exists(newPath));
if (newPath.Contains(" "))
newPath = string.Format("\"{0}\"", newPath);
using (var programKey = rootKey.CreateSubKey(programName, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
var oldDebugger = programKey.GetValue("Debugger") as string;
programKey.SetValue("Debugger", newPath, RegistryValueKind.String);
return oldDebugger;
}
}
static void RestoreKey(RegistryKey rootKey, string programName, string oldPath)
{
Debug.Assert(rootKey != null);
Debug.Assert(!string.IsNullOrEmpty(programName));
if (oldPath != null)
{
using (var programKey = rootKey.OpenSubKey(programName, RegistryKeyPermissionCheck.ReadWriteSubTree))
programKey.SetValue("Debugger", oldPath);
}
else
{
rootKey.DeleteSubKey(programName);
}
}
}
}