Monday, 16 August 2010

Agregar tu programa al inicio de Windows en C# y VB.NET

Con este codigo puedes iniciar tu aplicacion con Windows:

Codigo C#:

/*
* Creado por tttony 2010
* http://tttony.blogspot.com/
*
* POR FAVOR NO BORRES ESTE COMENTARIO
*/
RegistryKey hklm = Registry.LocalMachine;
hklm = hklm.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Run");
string path = hklm.GetValue(Application.ProductName).ToString();

string thisApp = Application.ExecutablePath.ToUpper();

if (path != thisApp) // No se inicia con windows
{
hklm.SetValue(Application.ProductName, thisApp);
}

hklm.Close();


Codigo VB.NET:

'
' * Creado por tttony 2010
' * http://tttony.blogspot.com/
' *
' * POR FAVOR NO BORRES ESTE COMENTARIO
'

Dim hklm As RegistryKey = Registry.LocalMachine
hklm = hklm.CreateSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Run")
Dim path As String = hklm.GetValue(Application.ProductName).ToString()

Dim thisApp As String = Application.ExecutablePath.ToUpper()

If path <> thisApp Then
' No se inicia con windows
hklm.SetValue(Application.ProductName, thisApp)
End If

hklm.Close()




Publicado en tttony.blogspot.com

Guardar configuracion previa en C# y VB.NET

Cada vez que compilas tu programa en C# cambia la version del ensamblado y por consiguiente la aplicacion crea una nueva carpeta:


C:\Documents and Settings\Usuario\Configuración local\Datos de programa\NOMBREPROGRAMA\NOMREDELEJECUTABLE.EXE_Url_2ha3w3vmz3qfzpaloruetfyed\1.0.3880.23525\app.config


Otra compilacion:

C:\Documents and Settings\Usuario\Configuración local\Datos de programa\NOMBREPROGRAMA\NOMREDELEJECUTABLE.EXE_Url_2ha3w3vmz3qfzpaloruetfyed\1.0.3880.24678\app.config


Entonces ahi tendras problemas con la configuracion y tendras que configurar el programa cada vez que lo compiles

Para evitar esto agrega este codigo, normalmente lo agrego en el archivo Program.cs de la solucion:

Codigo C#:

/*
* Importar la ultima configuracion
*/
Version appVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;

// Cambio la version del ensamblado???
// si es asi entonces guardalo
if (Properties.Settings.Default.ApplicationVersion != appVersion.ToString())
{
Properties.Settings.Default.Upgrade(); // <-- aqui importa la configuracion anterior
Properties.Settings.Default.ApplicationVersion = appVersion.ToString();
Properties.Settings.Default.Save();
}



Codigo VB.NET:

'
' * Importar la ultima configuracion
'

Dim appVersion As Version = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version

' Cambio la version del ensamblado???
' si es asi entonces guardalo
If Properties.Settings.[Default].ApplicationVersion <> appVersion.ToString() Then
Properties.Settings.[Default].Upgrade()
' <-- aqui importa la configuracion anterior
Properties.Settings.[Default].ApplicationVersion = appVersion.ToString()
Properties.Settings.[Default].Save()
End If


Como veras tendras que agregar un campo de configuracion llamado ApplicationVersion


Publicado en tttony.blogspot.com

BrowserFolder en C# y VB.NET

Necesitado en un BrowserFolder me encontre con este:

Codigo C#:

folderBrowserDialog1.Description = "Buscar el directorio";

// Para tener un directorio de inicio propio debes primero
// asignar a RootFolder = Environment.SpecialFolder.MyComputer
// luego en la siguiente linea escribes el directorio de inicio
// en SelectedPath

folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer;
folderBrowserDialog1.SelectedPath = Application.StartupPath; // <-- Directorio de inicio

if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
txtReportsPath.Text = folderBrowserDialog1.SelectedPath;
}


Codigo VB.NET:

folderBrowserDialog1.Description = "Buscar el directorio"
' Para tener un directorio de inicio propio debes primero
' asignar a RootFolder = Environment.SpecialFolder.MyComputer
' luego en la siguiente linea escribes el directorio de inicio
' en SelectedPath
folderBrowserDialog1.RootFolder = Environment.SpecialFolder.MyComputer
folderBrowserDialog1.SelectedPath = Application.StartupPath ' <-- Directorio de inicio
If folderBrowserDialog1.ShowDialog() = DialogResult.OK Then
txtReportsPath.Text = folderBrowserDialog1.SelectedPath
End if


Pues bien o mejor dicho mal, ya que este control no permite ver carpetas en la red, si que malo no???

Buscando en la web, me encontre con la funcion SHBrowseForFolder de la API de Windows, segui buscando y encontre este codigo que tambien venia sin el InitDir, asi que lo modifique:

Codigo C#:

using System;
using System.Diagnostics;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WINAPI32
{
/*
* Codigo original de netomatix.com
* http://www.netomatix.com/FolderBrowser.aspx
*
* Modificado para tener un directorio de inicio por: tttony 2010
* http://tttony.blogspot.com/
*
* POR FAVOR NO BORRAR ESTE COMENTARIO
*/
public delegate int BrowseCallbackProc(IntPtr hwnd, int uMsg, IntPtr wParam, IntPtr lParam);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
[ComVisible(true)]
public class BROWSEINFO
{
public IntPtr hwndOwner;
public IntPtr pidlRoot;
public IntPtr pszDisplayName;
public string lpszTitle;
public int ulFlags;
public BrowseCallbackProc lpfn;
public IntPtr lParam;
public int iImage;

}

public class Win32SDK
{
[DllImport("shell32.dll", PreserveSig = true, CharSet = CharSet.Auto)]
public static extern IntPtr SHBrowseForFolder(BROWSEINFO bi);

[DllImport("shell32.dll", PreserveSig = true, CharSet = CharSet.Auto)]
public static extern bool SHGetPathFromIDList(IntPtr pidl, IntPtr pszPath);

[DllImport("shell32.dll", PreserveSig = true, CharSet = CharSet.Auto)]
public static extern int SHGetSpecialFolderLocation(IntPtr hwnd, int csidl, ref IntPtr ppidl);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, string lParam);

}

public enum BrowseForFolderMessages
{
BFFM_ENABLEOK = 0x465,
BFFM_INITIALIZED = 1,
BFFM_IUNKNOWN = 5,
BFFM_SELCHANGED = 2,
BFFM_SETEXPANDED = 0x46a,
BFFM_SETOKTEXT = 0x469,
BFFM_SETSELECTIONA = 0x466,
BFFM_SETSELECTIONW = 0x467,
BFFM_SETSTATUSTEXTA = 0x464,
BFFM_SETSTATUSTEXTW = 0x468,
BFFM_VALIDATEFAILEDA = 3,
BFFM_VALIDATEFAILEDW = 4
}

[Flags, Serializable]
public enum BrowseFlags
{
BIF_DEFAULT = 0x0000,
BIF_BROWSEFORCOMPUTER = 0x1000,
BIF_BROWSEFORPRINTER = 0x2000,
BIF_BROWSEINCLUDEFILES = 0x4000,
BIF_BROWSEINCLUDEURLS = 0x0080,
BIF_DONTGOBELOWDOMAIN = 0x0002,
BIF_EDITBOX = 0x0010,
BIF_NEWDIALOGSTYLE = 0x0040,
BIF_NONEWFOLDERBUTTON = 0x0200,
BIF_RETURNFSANCESTORS = 0x0008,
BIF_RETURNONLYFSDIRS = 0x0001,
BIF_SHAREABLE = 0x8000,
BIF_STATUSTEXT = 0x0004,
BIF_UAHINT = 0x0100,
BIF_VALIDATE = 0x0020,
BIF_NOTRANSLATETARGETS = 0x0400,
}

public class FolderBrowser
{
private string m_strDirectoryPath;
private string m_strTitle;
private string m_strDisplayName;
private BrowseFlags m_Flags;
private string m_initDir = null;

public FolderBrowser()
{
m_Flags = BrowseFlags.BIF_DEFAULT;
m_strTitle = "";
}

public string DirectoryPath
{
get { return this.m_strDirectoryPath; }
}

public string DisplayName
{
get { return this.m_strDisplayName; }
}

public string Title
{
set { this.m_strTitle = value; }
}

public BrowseFlags Flags
{
set { this.m_Flags = value; }
}

public DialogResult ShowDialog()
{
BROWSEINFO bi = new BROWSEINFO();
bi.pszDisplayName = IntPtr.Zero;
//bi.lpfn = IntPtr.Zero;
/*
* InitDir??
*/
bi.lpfn = new BrowseCallbackProc(browserCallBack);
bi.lParam = IntPtr.Zero;
bi.lpszTitle = "Select Folder";
IntPtr idListPtr = IntPtr.Zero;
IntPtr pszPath = IntPtr.Zero;
try
{
if (this.m_strTitle.Length != 0)
{
bi.lpszTitle = this.m_strTitle;
}
bi.ulFlags = (int)this.m_Flags;
bi.pszDisplayName = Marshal.AllocHGlobal(256);
// Call SHBrowseForFolder
idListPtr = Win32SDK.SHBrowseForFolder(bi);

// Check if the user cancelled out of the dialog or not.
if (idListPtr == IntPtr.Zero)
{
return DialogResult.Cancel;
}

// Allocate ncessary memory buffer to receive the folder path.
pszPath = Marshal.AllocHGlobal(256);
// Call SHGetPathFromIDList to get folder path.
bool bRet = Win32SDK.SHGetPathFromIDList(idListPtr, pszPath);
// Convert the returned native poiner to string.
m_strDirectoryPath = Marshal.PtrToStringAuto(pszPath);
this.m_strDisplayName = Marshal.PtrToStringAuto(bi.pszDisplayName);
}
catch (Exception ex)
{
Trace.WriteLine(ex.Message);
return DialogResult.Abort;
}
finally
{
// Free the memory allocated by shell.
if (idListPtr != IntPtr.Zero)
{
Marshal.FreeHGlobal(idListPtr);
}
if (pszPath != IntPtr.Zero)
{
Marshal.FreeHGlobal(pszPath);
}
if (bi != null)
{
Marshal.FreeHGlobal(bi.pszDisplayName);
}
}
return DialogResult.OK;
}

private IntPtr GetStartLocationPath()
{
return IntPtr.Zero;
}

public string InitDir
{
set { this.m_initDir = value; }
}

private int browserCallBack(IntPtr hWnd, int uMsg, IntPtr wParam, IntPtr lParam)
{
if (uMsg == (int)BrowseForFolderMessages.BFFM_INITIALIZED)
{
/*
* Con BFFM_SETSELECTIONW todo bien
*/
Win32SDK.SendMessage(hWnd, (int)BrowseForFolderMessages.BFFM_SETSELECTIONW, 1, this.m_initDir);
}

return 0;
}
}

}


Codigo VB.NET:

Imports System.Diagnostics
Imports System.Collections
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Windows.Forms
Imports System.Runtime.InteropServices

Namespace WINAPI32
'
' * Codigo original de netomatix.com
' * http://www.netomatix.com/FolderBrowser.aspx
' *
' * Modificado para tener un directorio de inicio por: tttony 2010
' * http://tttony.blogspot.com/
' *
' * POR FAVOR NO BORRAR ESTE COMENTARIO
'

Public Delegate Function BrowseCallbackProc(hwnd As IntPtr, uMsg As Integer, wParam As IntPtr, lParam As IntPtr) As Integer

_
_
Public Class BROWSEINFO
Public hwndOwner As IntPtr
Public pidlRoot As IntPtr
Public pszDisplayName As IntPtr
Public lpszTitle As String
Public ulFlags As Integer
Public lpfn As BrowseCallbackProc
Public lParam As IntPtr
Public iImage As Integer

End Class

Public Class Win32SDK
_
Public Shared Function SHBrowseForFolder(bi As BROWSEINFO) As IntPtr
End Function

_
Public Shared Function SHGetPathFromIDList(pidl As IntPtr, pszPath As IntPtr) As Boolean
End Function

_
Public Shared Function SHGetSpecialFolderLocation(hwnd As IntPtr, csidl As Integer, ByRef ppidl As IntPtr) As Integer
End Function

_
Public Shared Function SendMessage(hWnd As IntPtr, Msg As Integer, wParam As Integer, lParam As String) As IntPtr
End Function

End Class

Public Enum BrowseForFolderMessages
BFFM_ENABLEOK = &H465
BFFM_INITIALIZED = 1
BFFM_IUNKNOWN = 5
BFFM_SELCHANGED = 2
BFFM_SETEXPANDED = &H46a
BFFM_SETOKTEXT = &H469
BFFM_SETSELECTIONA = &H466
BFFM_SETSELECTIONW = &H467
BFFM_SETSTATUSTEXTA = &H464
BFFM_SETSTATUSTEXTW = &H468
BFFM_VALIDATEFAILEDA = 3
BFFM_VALIDATEFAILEDW = 4
End Enum

_
Public Enum BrowseFlags
BIF_DEFAULT = &H0
BIF_BROWSEFORCOMPUTER = &H1000
BIF_BROWSEFORPRINTER = &H2000
BIF_BROWSEINCLUDEFILES = &H4000
BIF_BROWSEINCLUDEURLS = &H80
BIF_DONTGOBELOWDOMAIN = &H2
BIF_EDITBOX = &H10
BIF_NEWDIALOGSTYLE = &H40
BIF_NONEWFOLDERBUTTON = &H200
BIF_RETURNFSANCESTORS = &H8
BIF_RETURNONLYFSDIRS = &H1
BIF_SHAREABLE = &H8000
BIF_STATUSTEXT = &H4
BIF_UAHINT = &H100
BIF_VALIDATE = &H20
BIF_NOTRANSLATETARGETS = &H400
End Enum

Public Class FolderBrowser
Private m_strDirectoryPath As String
Private m_strTitle As String
Private m_strDisplayName As String
Private m_Flags As BrowseFlags
Private m_initDir As String = Nothing

Public Sub New()
m_Flags = BrowseFlags.BIF_DEFAULT
m_strTitle = ""
End Sub

Public ReadOnly Property DirectoryPath() As String
Get
Return Me.m_strDirectoryPath
End Get
End Property

Public ReadOnly Property DisplayName() As String
Get
Return Me.m_strDisplayName
End Get
End Property

Public WriteOnly Property Title() As String
Set
Me.m_strTitle = value
End Set
End Property

Public WriteOnly Property Flags() As BrowseFlags
Set
Me.m_Flags = value
End Set
End Property

Public Function ShowDialog() As DialogResult
Dim bi As New BROWSEINFO()
bi.pszDisplayName = IntPtr.Zero
'bi.lpfn = IntPtr.Zero;
'
' * InitDir??
'

bi.lpfn = New BrowseCallbackProc(AddressOf browserCallBack)
bi.lParam = IntPtr.Zero
bi.lpszTitle = "Select Folder"
Dim idListPtr As IntPtr = IntPtr.Zero
Dim pszPath As IntPtr = IntPtr.Zero
Try
If Me.m_strTitle.Length <> 0 Then
bi.lpszTitle = Me.m_strTitle
End If
bi.ulFlags = CInt(Me.m_Flags)
bi.pszDisplayName = Marshal.AllocHGlobal(256)
' Call SHBrowseForFolder
idListPtr = Win32SDK.SHBrowseForFolder(bi)

' Check if the user cancelled out of the dialog or not.
If idListPtr = IntPtr.Zero Then
Return DialogResult.Cancel
End If

' Allocate ncessary memory buffer to receive the folder path.
pszPath = Marshal.AllocHGlobal(256)
' Call SHGetPathFromIDList to get folder path.
Dim bRet As Boolean = Win32SDK.SHGetPathFromIDList(idListPtr, pszPath)
' Convert the returned native poiner to string.
m_strDirectoryPath = Marshal.PtrToStringAuto(pszPath)
Me.m_strDisplayName = Marshal.PtrToStringAuto(bi.pszDisplayName)
Catch ex As Exception
Trace.WriteLine(ex.Message)
Return DialogResult.Abort
Finally
' Free the memory allocated by shell.
If idListPtr <> IntPtr.Zero Then
Marshal.FreeHGlobal(idListPtr)
End If
If pszPath <> IntPtr.Zero Then
Marshal.FreeHGlobal(pszPath)
End If
If bi IsNot Nothing Then
Marshal.FreeHGlobal(bi.pszDisplayName)
End If
End Try
Return DialogResult.OK
End Function

Private Function GetStartLocationPath() As IntPtr
Return IntPtr.Zero
End Function

Public WriteOnly Property InitDir() As String
Set
Me.m_initDir = value
End Set
End Property

Private Function browserCallBack(hWnd As IntPtr, uMsg As Integer, wParam As IntPtr, lParam As IntPtr) As Integer
If uMsg = CInt(BrowseForFolderMessages.BFFM_INITIALIZED) Then
'
' * Con BFFM_SETSELECTIONW todo bien
'

Win32SDK.SendMessage(hWnd, CInt(BrowseForFolderMessages.BFFM_SETSELECTIONW), 1, Me.m_initDir)
End If

Return 0
End Function
End Class

End Namespace



Como usarlo??

Codigo C#:

FolderBrowser browser = new FolderBrowser();
browser.Title = "Buscar el directorio";
browser.Flags = BrowseFlags.BIF_NEWDIALOGSTYLE | BrowseFlags.BIF_NONEWFOLDERBUTTON;
browser.InitDir = Application.StartupPath; // <-- el directorio de inicio
if (browser.ShowDialog() == DialogResult.OK)
{
txtPath.Text = browser.DirectoryPath;
}


Codigo VB.NET:

Dim browser As New FolderBrowser()
browser.Title = "Buscar el directorio"
browser.Flags = BrowseFlags.BIF_NEWDIALOGSTYLE Or BrowseFlags.BIF_NONEWFOLDERBUTTON
browser.InitDir = Application.StartupPath ' <-- el directorio de inicio
If browser.ShowDialog() = DialogResult.OK Then
txtPath.Text = browser.DirectoryPath
End if



Publicado en tttony.blogspot.com

Wednesday, 4 August 2010

Instalar Office 2007 Enterprise desatendido

Buscando en la web me encontre de que existe una manera de instalar el Office 2007 Enterprise de forma desatendida, pues bien segun he leido la unica version que se puede instalar desatendidamente es la version Enterprise:


La forma de hacerlo es configurar el Office mediante este comando:

C:\office2007\setup.exe /admin


Luego de seguir los pasos que te indican alli, al final guardas un archivo en el menu Archivo --> Guardar con la extension desatendido.MSP y usandolo de esta manera:

OJO ESTE METODO NO ME FUNCIONO!!! SIGUE LEYENDO

C:\office2007\setup.exe /adminfile desatendido.msp


Se supone que se deberia de instalar sin preguntar nada, sin embargo no es asi, al ejecutar este ultimo comando te abre la ventana con el boton Continuar osea que no es desatendido.


Pero existe otra manera de hacerlo y es editando el archivo:

Enterprise.WW\config.xml



<Configuration Product="Enterprise">

<Display Level="basic" CompletionNotice="no" SuppressModal="yes" AcceptEula="yes" />

<!-- <Logging Type="standard" Path="%temp%" Template="Microsoft Office Enterprise Setup(*).txt" /> -->

<PIDKEY Value="AQUITUCODIGOSINELGUION" />

<USERNAME Value="PC" />

<COMPANYNAME Value="PC" />

<!-- <INSTALLLOCATION Value="%programfiles%\Microsoft Office" /> -->

<!-- <LIS CACHEACTION="CacheOnly" /> -->

<!-- <SOURCELIST Value="\\server1\share\Office12;\\server2\share\Office12" /> -->

<!-- <DistributionPoint Location="\\server\share\Office12" /> -->

<!-- <OptionState Id="OptionID" State="absent" Children="force" /> -->

<!-- <Setting Id="Reboot" Value="IfNeeded" /> -->

<!-- <Command Path="msiexec.exe" Args="/i \\server\share\my.msi" QuietArg="/q" ChainPosition="after" Execute="install" /> -->

</Configuration>


El archivo esta oculto y ademas no se puede escribir en el asi que primero guardalo por ejemplo en el Escritorio y luego lo copias y reemplazas en el directorio Enterprise.WW

Basicamente lo que se hace es que el modo de presentacion sea el basico:
Display Level="basic"

No avisar cuando termine:
CompletionNotice="no"

Suprimimos el modal:
SuppressModal="yes"

Y aceptamos la licencia:
AcceptEula="yes"



Para ejecutarlo haz lo siguiente:

C:\office2007\setup.exe /config Enterprise.WW\config.xml



NOTA: obviamente cambia el directorio por el tuyo


Publicado en tttony.blogspot.com

Thursday, 15 July 2010

Resetear BIOS de una Lenovo 3000 C200




Este post es especifico para la laptop Lenovo 3000 C200, los fabricantes, en este caso Lenovo, proveen en su pagina web un manual de intrucciones paso a paso de como desarmar una laptop

AQUI puedes ingresar el modelo/serie de la laptop y les aparecera el manual detallado de como desarmar la laptop, el link es especifico para Venezuela, si no aparece tu modelo entra en: (la laptop esta descontinuada y no encontraras guias ni manuales en la pagina de Lenovo)

1. lenovo.com
2. Soporte y Descargas
3. Guias y manuales
4. Introduce el modelo/serie de la laptop


Introduccion




En estos dias me he topado con una laptop Lenovo 3000 C200 que te pedia contraseña para iniciar, ni siquiera te deja entrar al BIOS, asi que habia que resetear el BIOS, pero como?

Buscando en la web de lenovo, me lei un manual, que te decia como resetear el BIOS (pagina no disponible) y funciono a la perfeccion, sin necesidad de quitar la pila, tan solo hay que hacer contacto para crear un corto


Pasos para resetear la BIOS



  1. Desconectar la bateria de la portatil
  2. Desconectar el cargador
  3. Debajo, quita la tapa donde estan las memorias y retira las memorias
  4. Ubica esto:




  5. Con un destornillador haz contacto por un rato en esa zona
  6. Listo!!


Publicado en tttony.blogspot.com

Monday, 5 July 2010

Problemas con las fechas en Access en C# y VB.NET

Si han tenido problemas para buscar filas con determinadas fechas, la fecha debe ser con este formato: YYYY/MM/DD de lo contrario tendras resultados indeseables como los que he tenido, aqui les dejo esta funcion:

Codigo C#:

// Darle formato a la fecha
private string ToDBDate(DateTime dt)
{
return dt.Year + "/" + dt.Month + "/" + dt.Day;
}


Codigo VB.NET:

' Darle formato a la fecha
Private Function ToDBDate(dt As DateTime) As String

Return dt.Year & "/" & dt.Month & "/" & dt.Day

End Function


EL otro problema que surge es con sentencias BETWEEN

Codigo C#:

string sql = String.Format("SELECT * FROM table1 WHERE datetime BETWEEN #{0} 00:00:00# AND #{1} 23:59:59#", ToDBDate(fromDateTime), ToDBDate(toDateTime));


Codigo VB.NET:

Dim sql As String = String.Format("SELECT * FROM table1 WHERE datetime BETWEEN #{0} 00:00:00# AND #{1} 23:59:59#", ToDBDate(
fromDateTime), ToDBDate(toDateTime))


Asi el resultado sera el que buscas


Publicado en tttony.blogspot.com

Wednesday, 12 May 2010

Reacciones en tus posts en Blogger

Para que tus visitantes voten por tus post debes activar las reacciones en tus post, sigue estos pasos:

1. Entra en Blogger
2. Click en Diseño
3. En el Gadget "Entradas del Blog" click en editar
4. Activa la casilla Reacciones
5. Y listo!!!

NOTA: si no te aparecen las casillas para votar en tu post entonces hay que editar la plantilla:

1. Entra en tu cuenta Blogger
2. Click en Diseño
3. Click en Edición HTML y activa Expandir plantillas de artilugios
4. Busca esta linea: (en Firefox Ctrl+F)


<p><dat:post.body/></p>


5. Abajo de esa linea pega este codigo


Publicado en tttony.blogspot.com